1#define DEBUG 1 2#include <Debug.h> 3#include <OS.h> 4#include <errno.h> 5#include <socket.h> 6#include <string.h> 7#include <Application.h> 8#include "ksocket_internal.h" 9 10sem_id printf_sem; 11 12static void send_reply (port_id port, const void *reply, size_t size) 13{ 14 status_t result; 15 16 do 17 { 18 result=write_port (port,0,reply,size); 19 } 20 while (result==B_INTERRUPTED); 21 22 ASSERT (result>=B_OK); 23} 24 25static void ks_socket (const struct ks_socket_param *param) 26{ 27 struct ks_socket_reply reply; 28 29 reply.result=socket (param->family,param->type,param->proto); 30 reply.header.error=errno; 31 32 send_reply (param->header.port,&reply,sizeof(reply)); 33} 34 35static void ks_multi1 (int32 code, const struct ks_bind_param *param) 36{ 37 struct ks_bind_reply reply; 38 39 if (code==KS_BIND) 40 reply.result=bind (param->fd,(const struct sockaddr *)param->addr,param->size); 41 else 42 reply.result=connect (param->fd,(const struct sockaddr *)param->addr,param->size); 43 44 reply.header.error=errno; 45 46 send_reply (param->header.port,&reply,sizeof(reply)); 47} 48 49static void ks_multi2 (int32 code, const struct ks_getsockname_param *param) 50{ 51 struct sockaddr *addr=(struct sockaddr *)malloc(param->size); 52 int size=param->size; 53 int result; 54 size_t replySize; 55 struct ks_getsockname_reply *reply; 56 57 switch (code) 58 { 59 case KS_GETSOCKNAME: 60 result=getsockname(param->fd,addr,&size); 61 break; 62 case KS_GETPEERNAME: 63 result=getpeername(param->fd,addr,&size); 64 break; 65 case KS_ACCEPT: 66 result=accept(param->fd,addr,&size); 67 break; 68 } 69 70 if (result<0) 71 size=0; 72 73 replySize=sizeof(struct ks_getsockname_reply)+size; 74 reply=(struct ks_getsockname_reply *)malloc(replySize); 75 reply->result=result; 76 reply->header.error=errno; 77 78 if (result>=0) 79 { 80 reply->size=size; 81 memcpy (reply->addr,addr,size); 82 } 83 84 send_reply (param->header.port,reply,replySize); 85 86 free (reply); 87 free (addr); 88} 89 90static void ks_recvfrom (const struct ks_recvfrom_param *param) 91{ 92 char *buffer=(char *)malloc(param->size); 93 struct sockaddr *addr=(struct sockaddr *)malloc(param->fromlen); 94 int fromlen=param->fromlen; 95 ssize_t result; 96 size_t replySize; 97 struct ks_recvfrom_reply *reply; 98 99 result=recvfrom(param->fd,buffer,param->size,param->flags,addr,&fromlen); 100 101 if (result<0) 102 replySize=sizeof(struct ks_recvfrom_reply); 103 else 104 replySize=sizeof(struct ks_recvfrom_reply)+fromlen+result; 105 106 reply=(struct ks_recvfrom_reply *)malloc(replySize); 107 reply->result=result; 108 reply->header.error=errno; 109 110 if (result>=0) 111 { 112 reply->fromlen=fromlen; 113 memcpy (reply->data,buffer,result); 114 memcpy (reply->data+result,addr,fromlen); 115 } 116 117 send_reply (param->header.port,reply,replySize); 118 119 free (reply); 120 free (addr); 121 free (buffer); 122} 123 124static void ks_sendto (const struct ks_sendto_param *param) 125{ 126 struct ks_sendto_reply reply; 127 128 reply.result=sendto (param->fd,param->data,param->size,param->flags, 129 (const struct sockaddr *)(param->data+param->size), 130 param->tolen); 131 132 reply.header.error=errno; 133 134 send_reply (param->header.port,&reply,sizeof(reply)); 135} 136 137static void ks_recv (const struct ks_recv_param *param) 138{ 139 char *buffer=(char *)malloc(param->size); 140 ssize_t result; 141 size_t replySize; 142 struct ks_recv_reply *reply; 143 144 result=recv(param->fd,buffer,param->size,param->flags); 145 146 if (result<0) 147 replySize=sizeof(struct ks_recvfrom_reply); 148 else 149 replySize=sizeof(struct ks_recvfrom_reply)+result; 150 151 reply=(struct ks_recv_reply *)malloc(replySize); 152 reply->result=result; 153 reply->header.error=errno; 154 155 if (result>=0) 156 memcpy (reply->data,buffer,result); 157 158 send_reply (param->header.port,reply,replySize); 159 160 free (reply); 161 free (buffer); 162} 163 164static void ks_send (const struct ks_send_param *param) 165{ 166 struct ks_send_reply reply; 167 168 reply.result=send (param->fd,param->data,param->size,param->flags); 169 170 reply.header.error=errno; 171 172 send_reply (param->header.port,&reply,sizeof(reply)); 173} 174 175static void ks_listen (const struct ks_listen_param *param) 176{ 177 struct ks_listen_reply reply; 178 179 reply.result=listen (param->fd,param->backlog); 180 reply.header.error=errno; 181 182 send_reply (param->header.port,&reply,sizeof(reply)); 183} 184 185static void ks_closesocket (const struct ks_closesocket_param *param) 186{ 187 struct ks_closesocket_reply reply; 188 189 reply.result=closesocket (param->fd); 190 reply.header.error=errno; 191 192 send_reply (param->header.port,&reply,sizeof(reply)); 193} 194 195static status_t client_func (void *buffer) 196{ 197 thread_id from; 198 int32 code=receive_data (&from,NULL,0); 199 200 ASSERT (code>=B_OK); 201 202 switch (code) 203 { 204 case KS_SOCKET: 205 ks_socket ((const struct ks_socket_param *)buffer); 206 break; 207 208 case KS_BIND: 209 case KS_CONNECT: 210 ks_multi1 (code,(const struct ks_bind_param *)buffer); 211 break; 212 213 case KS_GETSOCKNAME: 214 case KS_GETPEERNAME: 215 case KS_ACCEPT: 216 ks_multi2 (code,(const struct ks_getsockname_param *)buffer); 217 break; 218 219 case KS_RECVFROM: 220 ks_recvfrom ((const struct ks_recvfrom_param *)buffer); 221 break; 222 223 case KS_SENDTO: 224 ks_sendto ((const struct ks_sendto_param *)buffer); 225 break; 226 227 case KS_RECV: 228 ks_recv ((const struct ks_recv_param *)buffer); 229 break; 230 231 case KS_SEND: 232 ks_send ((const struct ks_send_param *)buffer); 233 break; 234 235 case KS_LISTEN: 236 ks_listen ((const struct ks_listen_param *)buffer); 237 break; 238 239 case KS_CLOSESOCKET: 240 ks_closesocket ((const struct ks_closesocket_param *)buffer); 241 break; 242 243 case KS_MESSAGE: 244 { 245 while (acquire_sem (printf_sem)==B_INTERRUPTED) ; 246 247 printf ("%s\n",buffer); 248 249 while (release_sem (printf_sem)==B_INTERRUPTED) ; 250 break; 251 } 252 } 253 254 free (buffer); 255 256 return B_OK; 257} 258 259class CApplication : public BApplication 260{ 261 port_id port; 262 thread_id fTID; 263 264 static status_t WorkhorseWrapper (CApplication *me); 265 status_t Workhorse (); 266 267 public: 268 CApplication (const char *signature); 269 270 virtual void ReadyToRun(); 271 virtual bool QuitRequested(); 272}; 273 274CApplication::CApplication(const char *signature) 275 : BApplication (signature) 276{ 277} 278 279void 280CApplication::ReadyToRun() 281{ 282 resume_thread (fTID=spawn_thread((thread_func)WorkhorseWrapper,"Workhorse",B_NORMAL_PRIORITY,this)); 283} 284 285bool 286CApplication::QuitRequested() 287{ 288 if (!BApplication::QuitRequested()) 289 return false; 290 291 while (write_port(port,KS_QUIT,NULL,0)==B_INTERRUPTED) 292 ; 293 294 status_t result; 295 wait_for_thread (fTID,&result); 296 297 return true; 298} 299 300status_t 301CApplication::WorkhorseWrapper(CApplication *me) 302{ 303 return me->Workhorse(); 304} 305 306status_t 307CApplication::Workhorse() 308{ 309 char *buffer; 310 ssize_t bufferSize; 311 int32 code; 312 thread_id tid; 313 status_t result; 314 BList clientList; 315 316 printf_sem=create_sem (1,"printf_sem"); 317 318 if (printf_sem<B_OK) 319 return 1; 320 321 port=create_port (10,KSOCKET_DAEMON_NAME); 322 323 if (port<B_OK) 324 { 325 delete_sem (printf_sem); 326 return 1; 327 } 328 329 while (true) 330 { 331 do 332 { 333 bufferSize=port_buffer_size (port); 334 } 335 while (bufferSize==B_INTERRUPTED); 336 337 ASSERT (bufferSize>=B_OK); 338 339 buffer=(char *)malloc(bufferSize); 340 341 do 342 { 343 result=read_port (port,&code,buffer,bufferSize); 344 } 345 while (result==B_INTERRUPTED); 346 347 ASSERT (result>=B_OK); 348 349 if (code==KS_QUIT) 350 break; 351 352 tid=spawn_thread (client_func,"ksocketd_client",B_NORMAL_PRIORITY,buffer); 353 354 ASSERT (tid>=B_OK); 355 356 clientList.AddItem((void *)tid); 357 358 result=resume_thread (tid); 359 360 ASSERT (result>=B_OK); 361 362 result=send_data (tid,code,NULL,0); 363 364 ASSERT (result>=B_OK); 365 } 366 367 for (int32 i=clientList.CountItems()-1;i>=0;i--) 368 { 369 thread_id tid=(thread_id)clientList.RemoveItem(i); 370 status_t result; 371 wait_for_thread (tid,&result); 372 } 373 374 delete_sem (printf_sem); 375 delete_port (port); 376 377 return B_OK; 378} 379 380int main () 381{ 382 CApplication app(KSOCKETD_SIGNATURE); 383 384 app.Run(); 385 386 return 0; 387} 388