1 /* 2 * Copyright 2008-2013, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 /*! Provides the networking stack notification service. */ 7 8 #include <net_notifications.h> 9 10 #include <kernel.h> 11 #include <generic_syscall.h> 12 #include <Notifications.h> 13 #include <util/KMessage.h> 14 15 //#define TRACE_NOTIFICATIONS 16 #ifdef TRACE_NOTIFICATIONS 17 # define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x) 18 #else 19 # define TRACE(x...) ; 20 #endif 21 22 23 class NetNotificationService : public DefaultUserNotificationService { 24 public: 25 NetNotificationService(); 26 virtual ~NetNotificationService(); 27 28 void Notify(const KMessage& event); 29 30 protected: 31 virtual void LastReferenceReleased(); 32 virtual void FirstAdded(); 33 virtual void LastRemoved(); 34 }; 35 36 37 static NetNotificationService sNotificationService; 38 39 40 // #pragma mark - NetNotificationService 41 42 43 NetNotificationService::NetNotificationService() 44 : 45 DefaultUserNotificationService("network") 46 { 47 } 48 49 50 NetNotificationService::~NetNotificationService() 51 { 52 } 53 54 55 void 56 NetNotificationService::Notify(const KMessage& event) 57 { 58 uint32 opcode = event.GetInt32("opcode", 0); 59 if (opcode == 0) 60 return; 61 62 TRACE("notify for %lx\n", opcode); 63 64 DefaultUserNotificationService::Notify(event, opcode); 65 } 66 67 68 void 69 NetNotificationService::LastReferenceReleased() 70 { 71 // don't delete us here 72 } 73 74 75 void 76 NetNotificationService::FirstAdded() 77 { 78 // The reference counting doesn't work for us, as we'll have to 79 // ensure our module stays loaded. 80 module_info* dummy; 81 get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy); 82 } 83 84 85 void 86 NetNotificationService::LastRemoved() 87 { 88 // Give up the reference _AddListener() 89 put_module(NET_NOTIFICATIONS_MODULE_NAME); 90 } 91 92 93 // #pragma mark - User generic syscall 94 95 96 static status_t 97 net_notifications_control(const char *subsystem, uint32 function, void *buffer, 98 size_t bufferSize) 99 { 100 struct net_notifications_control control; 101 if (bufferSize != sizeof(struct net_notifications_control) 102 || function != NET_NOTIFICATIONS_CONTROL_WATCHING) 103 return B_BAD_VALUE; 104 if (!IS_USER_ADDRESS(buffer) || user_memcpy(&control, buffer, 105 sizeof(struct net_notifications_control)) < B_OK) 106 return B_BAD_ADDRESS; 107 108 if (control.flags != 0) { 109 return sNotificationService.UpdateUserListener(control.flags, 110 control.port, control.token); 111 } 112 113 return sNotificationService.RemoveUserListeners(control.port, 114 control.token); 115 } 116 117 118 // #pragma mark - exported module API 119 120 121 static status_t 122 send_notification(const KMessage* event) 123 { 124 sNotificationService.Notify(*event); 125 return B_OK; 126 } 127 128 129 static status_t 130 notifications_std_ops(int32 op, ...) 131 { 132 switch (op) { 133 case B_MODULE_INIT: 134 { 135 TRACE("init\n"); 136 137 new(&sNotificationService) NetNotificationService(); 138 status_t result = sNotificationService.Register(); 139 if (result != B_OK) 140 return result; 141 142 register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 143 net_notifications_control, 1, 0); 144 return B_OK; 145 } 146 case B_MODULE_UNINIT: 147 TRACE("uninit\n"); 148 149 unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1); 150 151 // TODO: due to the way the locking in the notification 152 // manager works, there's a potential race condition here 153 // where someone attempts to add a listener right as 154 // we're uninitializing. Needs to be looked at/resolved. 155 sNotificationService.Unregister(); 156 157 // we need to release the reference that was acquired 158 // on our behalf by the NotificationManager. 159 sNotificationService.ReleaseReference(); 160 sNotificationService.~NetNotificationService(); 161 return B_OK; 162 163 default: 164 return B_ERROR; 165 } 166 } 167 168 169 net_notifications_module_info sNotificationsModule = { 170 { 171 NET_NOTIFICATIONS_MODULE_NAME, 172 0, 173 notifications_std_ops 174 }, 175 176 send_notification 177 }; 178 179 module_info* modules[] = { 180 (module_info*)&sNotificationsModule, 181 NULL 182 }; 183