/addons/Socket/source/IoSocket.c
C | 597 lines | 401 code | 104 blank | 92 comment | 38 complexity | 6813ecf8cb6b02d6c4847f2958a0edc8 MD5 | raw file
1//metadoc Socket copyright Steve Dekorte, 2004 2//metadoc Socket license BSD revised 3 4/*metadoc Socket description 5Interface to network communication. 6Sockets will auto yield to other coroutines while waiting on a request. 7All blocking operations use the timeout settings of the socket. 8Reads are appended to the socket's read buffer which can 9be accessed using the readBuffer method. 10 11Example: 12 13<pre> 14socket := Socket clone setHost("www.yahoo.com") setPort(80) connect 15if(socket error) then( write(socket error, "\n"); exit) 16 17socket write("GET /\n\n") 18 19while(socket read, Nop) 20if(socket error) then(write(socket error, "\n"); exit) 21 22write("read ", socket readBuffer length, " bytes\n") 23</pre> 24*/ 25 26//metadoc Socket category Networking 27 28 29/*doc Socket setHost(hostName) 30Translates hostName to an IP using asynchronous DNS and sets 31the host attribute. Returns self. 32*/ 33 34#include "IoSocket.h" 35#include "IoIPAddress.h" 36#include "IoState.h" 37#include "IoNumber.h" 38#include "IoSeq.h" 39#include "UArray.h" 40#include "List.h" 41 42IoSocket *IoMessage_locals_socketArgAt_(IoMessage *self, IoObject *locals, int n) 43{ 44 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n); 45 46 if (!ISSOCKET(v)) 47 { 48 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Socket"); 49 } 50 51 return v; 52} 53 54#define SOCKET(self) ((Socket *)IoObject_dataPointer(self)) 55 56void IoSocket_tagCleanup(IoTag *self) 57{ 58 Socket_GlobalCleanup(); 59} 60 61IoTag *IoSocket_newTag(void *state) 62{ 63 IoTag *tag = IoTag_newWithName_("Socket"); 64 IoTag_state_(tag, state); 65 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoSocket_free); 66 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoSocket_rawClone); 67 IoTag_cleanupFunc_(tag, (IoTagCleanupFunc *)IoSocket_tagCleanup); 68 Socket_GlobalInit(); 69 return tag; 70} 71 72IoSocket *IoSocket_proto(void *state) 73{ 74 IoObject *self = IoObject_new(state); 75 76 IoObject_tag_(self, IoSocket_newTag(state)); 77 IoObject_setDataPointer_(self, Socket_new()); 78 79 IoState_registerProtoWithFunc_((IoState *)state, self, IoSocket_proto); 80 81 { 82 IoMethodTable methodTable[] = { 83 {"asyncStreamOpen", IoSocket_asyncStreamOpen}, 84 {"asyncUdpOpen", IoSocket_asyncUdpOpen}, 85 {"isOpen", IoSocket_isOpen}, 86 {"isValid", IoSocket_isValid}, 87 {"isStream", IoSocket_isStream}, 88 89 {"asyncBind", IoSocket_asyncBind}, 90 {"asyncListen", IoSocket_asyncListen}, 91 {"asyncAccept", IoSocket_asyncAccept}, 92 93 {"asyncConnect", IoSocket_asyncConnect}, 94 95 {"asyncStreamRead", IoSocket_asyncStreamRead}, 96 {"asyncStreamWrite", IoSocket_asyncStreamWrite}, 97 98 {"asyncUdpRead", IoSocket_asyncUdpRead}, 99 {"asyncUdpWrite", IoSocket_asyncUdpWrite}, 100 101 {"close", IoSocket_close}, 102 {"descriptorId", IoSocket_descriptorId}, 103 104 {"setSocketReadBufferSize", IoSocket_setSocketReadBufferSize}, 105 {"setSocketWriteBufferSize", IoSocket_setSocketWriteBufferSize}, 106 107 {"getSocketReadLowWaterMark", IoSocket_getSocketReadLowWaterMark}, 108 {"getSocketWriteLowWaterMark", IoSocket_getSocketWriteLowWaterMark}, 109 110 {"setSocketReadLowWaterMark", IoSocket_setSocketReadLowWaterMark}, 111 {"setSocketWriteLowWaterMark", IoSocket_setSocketWriteLowWaterMark}, 112 113 {"setNoDelay", IoSocket_setNoDelay}, 114 115 {"errorNumber", IoSocket_errorNumber}, 116 {"errorDescription", IoSocket_errorDescription}, 117 118 {NULL, NULL} 119 }; 120 IoObject_addMethodTable_(self, methodTable); 121 } 122 123 return self; 124} 125 126IoSocket *IoSocket_rawClone(IoSocket *proto) 127{ 128 IoObject *self = IoObject_rawClonePrimitive(proto); 129 IoObject_setDataPointer_(self, Socket_new()); 130 return self; 131} 132 133IoSocket *IoSocket_new(void *state) 134{ 135 IoObject *proto = IoState_protoWithInitFunction_((IoState *)state, IoSocket_proto); 136 return IOCLONE(proto); 137} 138 139// ----------------------------------------------------------- 140 141IoSocket *IoSocket_newWithSocket_(void *state, Socket *socket) 142{ 143 IoSocket *self = IoSocket_new(state); 144 Socket_free(SOCKET(self)); 145 IoObject_setDataPointer_(self, socket); 146 return self; 147} 148 149void IoSocket_free(IoSocket *self) 150{ 151 Socket_free(SOCKET(self)); 152} 153 154// ---------------------------------------- 155 156IoSocket *IoSocket_rawSetupEvent_(IoSocket *self, IoObject *locals, IoMessage *m, char *eventSlotName) 157{ 158 IoObject *event = IoObject_rawGetSlot_(self, IOSYMBOL(eventSlotName)); 159 if(!event || ISNIL(event)) 160 { 161 IoState_error_(IOSTATE, m, "Expected %s slot to be set!", eventSlotName); 162 return IONIL(self); 163 } 164 else 165 { 166 IoObject_setSlot_to_(event, IOSYMBOL("descriptorId"), IoSocket_descriptorId(self, locals, m)); 167 return self; 168 } 169} 170 171IoSocket *IoSocket_rawSetupEvents(IoSocket *self, IoObject *locals, IoMessage *m) 172{ 173 IoSocket_rawSetupEvent_(self, locals, m, "readEvent"); 174 IoSocket_rawSetupEvent_(self, locals, m, "writeEvent"); 175 return self; 176} 177 178IoObject *IoSocket_descriptorId(IoSocket *self, IoObject *locals, IoMessage *m) 179{ 180 //doc Socket descriptorId Returns the socket's file descriptor id as a Number. 181 return IONUMBER((int) Socket_descriptor(SOCKET(self))); 182} 183 184SOCKET_DESCRIPTOR IoSocket_rawDescriptor(IoSocket *self) 185{ 186 return Socket_descriptor(SOCKET(self)); 187} 188 189// ---------------------------------------- 190 191IoObject *IoSocket_isStream(IoSocket *self, IoObject *locals, IoMessage *m) 192{ 193 //doc Socket isStream Returns true if the socket is a stream, false otherwise. 194 return IOBOOL(self, Socket_isStream(SOCKET(self))); 195} 196 197IoObject *IoSocket_isOpen(IoSocket *self, IoObject *locals, IoMessage *m) 198{ 199 //doc Socket isOpen Returns true if the socket is open, false otherwise. 200 return IOBOOL(self, Socket_isOpen(SOCKET(self))); 201} 202 203IoObject *IoSocket_isValid(IoSocket *self, IoObject *locals, IoMessage *m) 204{ 205 //doc Socket isValid Returns true if the socket is in valid state, closes the socket and returns false otherwise. 206 int isValid = Socket_isValid(SOCKET(self)); 207 208 if (!isValid) 209 IoSocket_close(self, locals, m); 210 211 return IOBOOL(self, isValid); 212} 213 214// ---------------------------------------- 215 216IoObject *IoSocket_asyncStreamOpen(IoSocket *self, IoObject *locals, IoMessage *m) 217{ 218 //doc Socket asyncStreamOpen Submits an async request to open the socket in stream mode and returns self immediately or an Error object on error. 219 220 Socket *socket = SOCKET(self); 221 SocketResetErrorStatus(); 222 223 if (Socket_streamOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket)) 224 { 225 IoSocket_rawSetupEvents(self, locals, m); 226 return self; 227 } 228 else 229 { 230 return SOCKETERROR("Failed to create stream socket"); 231 } 232} 233 234IoObject *IoSocket_asyncUdpOpen(IoSocket *self, IoObject *locals, IoMessage *m) 235{ 236 //doc Socket asyncUdpOpen Submits an async request to open the socket in UDP mode and returns self immediately or an Error object on error. 237 238 Socket *socket = SOCKET(self); 239 240 if (Socket_udpOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket)) 241 { 242 IoSocket_rawSetupEvents(self, locals, m); 243 return self; 244 } 245 else 246 { 247 return SOCKETERROR("Failed to create udp socket"); 248 } 249} 250 251// ---------------------------------------- 252 253IoObject *IoSocket_asyncConnect(IoSocket *self, IoObject *locals, IoMessage *m) 254{ 255 //doc Socket asyncConnect(ipAddressObject) Connects ti the given IPAddress and returns self or an Error object on error. 256 257 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0); 258 259 if (Socket_connectTo(SOCKET(self), address)) 260 { 261 return self; 262 } 263 else 264 { 265 if (Socket_connectToFailed()) 266 { 267 return SOCKETERROR("Socket connect failed"); 268 } 269 else 270 { 271 return IONIL(self); 272 } 273 } 274} 275 276IoObject *IoSocket_close(IoSocket *self, IoObject *locals, IoMessage *m) 277{ 278 //doc Socket close Closes the socket and returns self. Returns nil on error. 279 280 if (Socket_close(SOCKET(self))) 281 { 282 IoSocket_rawSetupEvents(self, locals, m); 283 return self; 284 } 285 else 286 { 287 if (Socket_closeFailed()) 288 { 289 return SOCKETERROR("Failed to close socket"); 290 } 291 else 292 { 293 return IONIL(self); 294 } 295 } 296} 297 298// server ------------------------------- 299 300IoObject *IoSocket_asyncBind(IoSocket *self, IoObject *locals, IoMessage *m) 301{ 302 //doc Socket asyncBind Binds the socket and returns self immediately or an Error object on error. 303 304 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0); 305 306 if (Socket_bind(SOCKET(self), address)) 307 { 308 return self; 309 } 310 else 311 { 312 return SOCKETERROR("Failed to bind socket"); 313 } 314} 315 316IoObject *IoSocket_asyncListen(IoSocket *self, IoObject *locals, IoMessage *m) 317{ 318 //doc Socket asyncListen Listens to the socket and returns self immediately or an Error object on error. 319 320 if (Socket_listen(SOCKET(self))) 321 { 322 return self; 323 } 324 else 325 { 326 return SOCKETERROR("Socket listen failed"); 327 } 328} 329 330IoObject *IoSocket_asyncAccept(IoSocket *self, IoObject *locals, IoMessage *m) 331{ 332 //doc Socket asyncAccept(ipAddressObject) Immediately returns a socket for an connection if one is available or nil otherwise. Returns an Error object on error. 333 334 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0); 335 Socket *socket = Socket_accept(SOCKET(self), address); 336 337 if (socket) 338 { 339 IoObject *newSocket = IoSocket_newWithSocket_(IOSTATE, socket); 340 newSocket = IoObject_initClone_(self, locals, m, newSocket); 341 return IoSocket_rawSetupEvents(newSocket, locals, m); 342 } 343 else 344 { 345 if (Socket_asyncFailed()) 346 { 347 return SOCKETERROR("Socket accept failed"); 348 } 349 else 350 { 351 return IONIL(self); 352 } 353 } 354} 355 356// stream ------------------------------- 357 358IoObject *IoSocket_asyncStreamRead(IoSocket *self, IoObject *locals, IoMessage *m) 359{ 360 /*doc Socket asyncStreamRead(aSeq, readSize) 361 Reads up to readSize number of bytes into aSeq if data is available. 362 Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected. 363 */ 364 365 IoSeq *bufferSeq = IoMessage_locals_mutableSeqArgAt_(m, locals, 0); 366 UArray *buffer = IoSeq_rawUArray(bufferSeq); 367 size_t readSize = IoMessage_locals_intArgAt_(m, locals, 1); 368 369 if (Socket_streamRead(SOCKET(self), buffer, readSize)) 370 { 371 return self; 372 } 373 374 if (Socket_asyncFailed()) 375 { 376 IoSocket_close(self, locals, m); 377 return SOCKETERROR("Socket stream read failed"); 378 } 379 380 //if (readSize == 0) //SocketErrorStatus() == 0) 381 if (SocketErrorStatus() == 0) 382 { 383 // 0 bytes means the other end disconnected 384 //printf("SocketErrorStatus() == 0, closing\n"); 385 IoSocket_close(self, locals, m); 386 } 387 388 return IONIL(self); 389} 390 391IoObject *IoSocket_asyncStreamWrite(IoSocket *self, IoObject *locals, IoMessage *m) 392{ 393 /*doc Socket asyncStreamWrite(aSeq, start, writeSize) 394 Writes the slice of aSeq from start to start + writeSize to the socket. 395 Returns self immediately if successful, otherwise closes the socket. 396 Returns an error object on Error. 397 Returns nil if the socket is disconnected. 398 */ 399 400 IoSeq *bufferSeq = IoMessage_locals_seqArgAt_(m, locals, 0); 401 UArray *buffer = IoSeq_rawUArray(bufferSeq); 402 size_t start = IoMessage_locals_intArgAt_(m, locals, 1); 403 size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 2); 404 size_t bytesWritten = Socket_streamWrite(SOCKET(self), buffer, start, writeSize); 405 406 if (bytesWritten) 407 { 408 UArray_removeRange(buffer, start, bytesWritten); 409 return self; 410 } 411 else 412 { 413 if (Socket_asyncFailed()) 414 { 415 IoSocket_close(self, locals, m); 416 return SOCKETERROR("Socket stream write failed"); 417 } 418 else 419 { 420 int errorNumber = SocketErrorStatus(); 421 422 if (errorNumber == ECONNRESET) IoSocket_close(self, locals, m); 423 return IONIL(self); 424 } 425 } 426} 427 428// udp ------------------------------ 429 430IoObject *IoSocket_asyncUdpRead(IoSocket *self, IoObject *locals, IoMessage *m) 431{ 432 /*doc Socket asyncUdpRead(ipAddress, aSeq, readSize) 433 Reads up to readSize number of bytes from ipAddress into aSeq if data is available. 434 Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected. 435 */ 436 437 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0); 438 UArray *buffer = IoSeq_rawUArray(IoMessage_locals_mutableSeqArgAt_(m, locals, 1)); 439 size_t readSize = IoMessage_locals_sizetArgAt_(m, locals, 2); 440 441 if (Socket_udpRead(SOCKET(self), address, buffer, readSize)) 442 { 443 return self; 444 } 445 else 446 { 447 if (Socket_asyncFailed()) 448 { 449 return SOCKETERROR("Socket udp read failed"); 450 } 451 else 452 { 453 return IONIL(self); 454 } 455 } 456} 457 458IoObject *IoSocket_asyncUdpWrite(IoSocket *self, IoObject *locals, IoMessage *m) 459{ 460 /*doc Socket asyncUdpWrite(ipAddress, aSeq, startIndex, readSize) 461 Writes readsize bytes from aSeq starting at startIndex to ipAddress. 462 Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected. 463 */ 464 465 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0); 466 UArray *buffer = IoSeq_rawUArray(IoMessage_locals_seqArgAt_(m, locals, 1)); 467 size_t start = IoMessage_locals_intArgAt_(m, locals, 2); 468 size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 3); 469 size_t bytesWritten = Socket_udpWrite(SOCKET(self), address, buffer, start, writeSize); 470 471 if (bytesWritten) 472 { 473 if (bytesWritten < writeSize) 474 { 475 return SOCKETERROR("Socket udp write failed"); 476 } 477 else 478 { 479 UArray_removeRange(buffer, start, bytesWritten); 480 return self; 481 } 482 } 483 else 484 { 485 if (Socket_asyncFailed()) 486 { 487 return SOCKETERROR("Socket udp write failed"); 488 } 489 else 490 { 491 return IONIL(self); 492 } 493 } 494} 495 496// ---------------------------------- 497 498IoObject *IoSocket_setSocketReadBufferSize(IoSocket *self, IoObject *locals, IoMessage *m) 499{ 500 //doc Socket setSocketReadBufferSize(numberOfBytes) Sets the read buffer size for the socket. Returns self on success or nil on error. 501 502 int size = IoMessage_locals_intArgAt_(m, locals, 0); 503 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(int)); 504 return (r == 0) ? self : IONIL(self); 505} 506 507IoObject *IoSocket_setSocketWriteBufferSize(IoSocket *self, IoObject *locals, IoMessage *m) 508{ 509 //doc Socket setSocketWriteBufferSize(numberOfBytes) Sets the write buffer size for the socket. Returns self on success or nil on error. 510 511 int size = IoMessage_locals_intArgAt_(m, locals, 0); 512 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)); 513 return (r == 0) ? self : IONIL(self); 514} 515 516IoObject *IoSocket_setSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m) 517{ 518 /*doc Socket setSocketReadLowWaterMark(numberOfBytes) 519 Sets the read low water mark for the socket. Returns self on success or nil on error. 520 */ 521 522 int size = IoMessage_locals_intArgAt_(m, locals, 0); 523 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, sizeof(int)); 524 return (r == 0) ? self : IONIL(self); 525} 526 527IoObject *IoSocket_setSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m) 528{ 529 /*doc Socket setSocketWriteLowWaterMark(numberOfBytes) 530 Sets the write low water mark for the socket. Returns self on success or nil on error. 531 */ 532 533 int size = IoMessage_locals_intArgAt_(m, locals, 0); 534 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, sizeof(int)); 535 return (r == 0) ? self : IONIL(self); 536} 537 538IoObject *IoSocket_getSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m) 539{ 540 /*doc Socket getSocketReadLowWaterMark 541 Returns the read low water mark for the socket on success or nil on error. 542 */ 543 544 int size = 0; 545 socklen_t length = sizeof(int); 546 //int r = 547 getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, &length); 548 // return (r == 0) ? IONUMBER(size) : IONIL(self); 549 return IONUMBER(size); 550} 551 552IoObject *IoSocket_getSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m) 553{ 554 /*doc Socket getSocketWriteLowWaterMark 555 Returns the write low water mark for the socket on success or nil on error. 556 */ 557 558 int size = 0; 559 socklen_t length = sizeof(int); 560 //int r = 561 getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, &length); 562 // return (r == 0) ? IONUMBER(size) : IONIL(self); 563 return IONUMBER(size); 564} 565 566#ifndef WIN32 567#include <sys/socket.h> 568#endif 569 570IoObject *IoSocket_setNoDelay(IoSocket *self, IoObject *locals, IoMessage *m) 571{ 572 /*doc Socket setNoDelay 573 Sets the socket to be no-delay. Returns self on success or nil on error. 574 */ 575 576 int r = -1; 577 #ifdef TCP_NODELAY 578 int flag = 1; 579 r = setsockopt(SOCKET(self)->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); 580 #endif 581 582 return (r == 0) ? self : IONIL(self); 583} 584 585IoObject *IoSocket_errorNumber(IoSocket *self, IoObject *locals, IoMessage *m) 586{ 587 //doc Socket errorNumber Returns the socket error number for the last error. 588 589 return IONUMBER(SocketErrorStatus()); 590} 591 592IoObject *IoSocket_errorDescription(IoSocket *self, IoObject *locals, IoMessage *m) 593{ 594 //doc Socket errorDescription Returns a description of the last error on the socket as a string. 595 596 return IOSYMBOL(Socket_errorDescription()); 597}