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