Addons updated to new doc format
[io.git] / addons / Socket / source / IoSocket.c
blobdc7e753251a7a4c832e19a91080229a8c4c7db82
1 /*metadoc Socket copyright
2 Steve Dekorte, 2004
3 */
5 /*metadoc Socket license
6 BSD revised
7 */
9 /*metadoc Socket dependsOn
10 SocketManager
13 /*metadoc Socket description
14 Interface to network communication.
15 Sockets will auto yield to other coroutines while waiting on a request.
16 All blocking operations use the timeout settings of the socket.
17 Reads are appended to the socket's read buffer which can
18 be accessed using the readBuffer method.
20 Example:
22 <code>
23 socket := Socket clone setHost("www.yahoo.com") setPort(80) connect
24 if(socket error) then( write(socket error, "\n"); exit)
26 socket write("GET /\n\n")
28 while(socket read, Nop)
29 if(socket error) then(write(socket error, "\n"); exit)
31 write("read ", socket readBuffer length, " bytes\n")
32 </code> """)
33 //metadoc category Networking")
37 /*doc Socket setHost(hostName)
38 Translates hostName to an IP using asynchronous DNS and sets
39 the host attribute. Returns self.
42 #include "IoSocket.h"
43 #include "IoIPAddress.h"
44 #include "IoState.h"
45 #include "IoNumber.h"
46 #include "IoSeq.h"
47 #include "UArray.h"
48 #include "List.h"
50 IoSocket *IoMessage_locals_socketArgAt_(IoMessage *self, IoObject *locals, int n)
52 IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
54 if (!ISSOCKET(v))
56 IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Socket");
59 return v;
62 #define SOCKET(self) ((Socket *)IoObject_dataPointer(self))
64 void IoSocket_tagCleanup(IoTag *self)
66 Socket_GlobalCleanup();
69 IoTag *IoSocket_newTag(void *state)
71 IoTag *tag = IoTag_newWithName_("Socket");
72 IoTag_state_(tag, state);
73 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoSocket_free);
74 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoSocket_rawClone);
75 IoTag_cleanupFunc_(tag, (IoTagCleanupFunc *)IoSocket_tagCleanup);
76 Socket_GlobalInit();
77 return tag;
80 IoSocket *IoSocket_proto(void *state)
82 IoObject *self = IoObject_new(state);
84 IoObject_tag_(self, IoSocket_newTag(state));
85 IoObject_setDataPointer_(self, Socket_new());
87 IoState_registerProtoWithFunc_((IoState *)state, self, IoSocket_proto);
90 IoMethodTable methodTable[] = {
91 {"asyncStreamOpen", IoSocket_asyncStreamOpen},
92 {"asyncUdpOpen", IoSocket_asyncUdpOpen},
93 {"isOpen", IoSocket_isOpen},
94 {"isValid", IoSocket_isValid},
95 {"isStream", IoSocket_isStream},
97 {"asyncBind", IoSocket_asyncBind},
98 {"asyncListen", IoSocket_asyncListen},
99 {"asyncAccept", IoSocket_asyncAccept},
101 {"asyncConnect", IoSocket_connectTo},
103 {"asyncStreamRead", IoSocket_asyncStreamRead},
104 {"asyncStreamWrite", IoSocket_asyncStreamWrite},
106 {"asyncUdpRead", IoSocket_udpRead},
107 {"asyncUdpWrite", IoSocket_udpWrite},
109 {"close", IoSocket_close},
110 {"descriptorId", IoSocket_descriptorId},
112 {"setSocketReadBufferSize", IoSocket_setSocketReadBufferSize},
113 {"setSocketWriteBufferSize", IoSocket_setSocketWriteBufferSize},
115 {"getSocketReadLowWaterMark", IoSocket_getSocketReadLowWaterMark},
116 {"getSocketWriteLowWaterMark", IoSocket_getSocketWriteLowWaterMark},
118 {"setSocketReadLowWaterMark", IoSocket_setSocketReadLowWaterMark},
119 {"setSocketWriteLowWaterMark", IoSocket_setSocketWriteLowWaterMark},
121 {"setNoDelay", IoSocket_setNoDelay},
123 {"errorNumber", IoSocket_errorNumber},
124 {"errorDescription", IoSocket_errorDescription},
126 {NULL, NULL}
128 IoObject_addMethodTable_(self, methodTable);
131 return self;
134 IoSocket *IoSocket_rawClone(IoSocket *proto)
136 IoObject *self = IoObject_rawClonePrimitive(proto);
137 IoObject_setDataPointer_(self, Socket_new());
138 return self;
141 IoSocket *IoSocket_new(void *state)
143 IoObject *proto = IoState_protoWithInitFunction_((IoState *)state, IoSocket_proto);
144 return IOCLONE(proto);
147 // -----------------------------------------------------------
149 IoSocket *IoSocket_newWithSocket_(void *state, Socket *socket)
151 IoSocket *self = IoSocket_new(state);
152 Socket_free(SOCKET(self));
153 IoObject_setDataPointer_(self, socket);
154 return self;
157 void IoSocket_free(IoSocket *self)
159 Socket_free(SOCKET(self));
162 // ----------------------------------------
164 IoSocket *IoSocket_rawSetupEvent_(IoSocket *self, IoObject *locals, IoMessage *m, char *eventSlotName)
166 IoObject *event = IoObject_rawGetSlot_(self, IOSYMBOL(eventSlotName));
167 if(!event || ISNIL(event))
169 IoState_error_(IOSTATE, m, "Expected %s slot to be set!", eventSlotName);
170 return IONIL(self);
172 else
174 IoObject_setSlot_to_(event, IOSYMBOL("descriptorId"), IoSocket_descriptorId(self, locals, m));
175 return self;
179 IoSocket *IoSocket_rawSetupEvents(IoSocket *self, IoObject *locals, IoMessage *m)
181 IoSocket_rawSetupEvent_(self, locals, m, "readEvent");
182 IoSocket_rawSetupEvent_(self, locals, m, "writeEvent");
183 return self;
186 IoObject *IoSocket_descriptorId(IoSocket *self, IoObject *locals, IoMessage *m)
188 return IONUMBER((int) Socket_descriptor(SOCKET(self)));
191 SOCKET_DESCRIPTOR IoSocket_rawDescriptor(IoSocket *self)
193 return Socket_descriptor(SOCKET(self));
196 // ----------------------------------------
198 IoObject *IoSocket_isStream(IoSocket *self, IoObject *locals, IoMessage *m)
200 return IOBOOL(self, Socket_isStream(SOCKET(self)));
203 IoObject *IoSocket_isOpen(IoSocket *self, IoObject *locals, IoMessage *m)
205 return IOBOOL(self, Socket_isOpen(SOCKET(self)));
208 IoObject *IoSocket_isValid(IoSocket *self, IoObject *locals, IoMessage *m)
210 int isValid = Socket_isValid(SOCKET(self));
212 if (!isValid)
213 IoSocket_close(self, locals, m);
215 return IOBOOL(self, isValid);
218 // ----------------------------------------
220 IoObject *IoSocket_asyncStreamOpen(IoSocket *self, IoObject *locals, IoMessage *m)
222 Socket *socket = SOCKET(self);
223 SocketResetErrorStatus();
225 if (Socket_streamOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket))
227 IoSocket_rawSetupEvents(self, locals, m);
228 return self;
230 else
232 return SOCKETERROR("Failed to create stream socket");
236 IoObject *IoSocket_asyncUdpOpen(IoSocket *self, IoObject *locals, IoMessage *m)
238 Socket *socket = SOCKET(self);
240 if (Socket_udpOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket))
242 IoSocket_rawSetupEvents(self, locals, m);
243 return self;
245 else
247 return SOCKETERROR("Failed to create udp socket");
251 // ----------------------------------------
253 IoObject *IoSocket_connectTo(IoSocket *self, IoObject *locals, IoMessage *m)
255 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
256 if (Socket_connectTo(SOCKET(self), address))
257 return self;
258 else
260 if (Socket_connectToFailed())
261 return SOCKETERROR("Socket connect failed");
262 else
263 return IONIL(self);
267 IoObject *IoSocket_close(IoSocket *self, IoObject *locals, IoMessage *m)
269 if (Socket_close(SOCKET(self)))
271 IoSocket_rawSetupEvents(self, locals, m);
272 return self;
274 else
276 if (Socket_closeFailed())
277 return SOCKETERROR("Failed to close socket");
278 else
279 return IONIL(self);
283 // server -------------------------------
285 IoObject *IoSocket_asyncBind(IoSocket *self, IoObject *locals, IoMessage *m)
287 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
288 if (Socket_bind(SOCKET(self), address))
289 return self;
290 else
291 return SOCKETERROR("Failed to bind socket");
294 IoObject *IoSocket_asyncListen(IoSocket *self, IoObject *locals, IoMessage *m)
296 if (Socket_listen(SOCKET(self)))
297 return self;
298 else
299 return SOCKETERROR("Socket listen failed");
302 IoObject *IoSocket_asyncAccept(IoSocket *self, IoObject *locals, IoMessage *m)
304 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
305 Socket *socket = Socket_accept(SOCKET(self), address);
306 if (socket)
308 IoObject *newSocket = IoSocket_newWithSocket_(IOSTATE, socket);
309 newSocket = IoObject_initClone_(self, locals, m, newSocket);
310 return IoSocket_rawSetupEvents(newSocket, locals, m);
312 else
314 if (Socket_asyncFailed())
315 return SOCKETERROR("Socket accept failed");
316 else
317 return IONIL(self);
321 // stream -------------------------------
323 IoObject *IoSocket_asyncStreamRead(IoSocket *self, IoObject *locals, IoMessage *m)
325 IoSeq *bufferSeq = IoMessage_locals_mutableSeqArgAt_(m, locals, 0);
326 UArray *buffer = IoSeq_rawUArray(bufferSeq);
327 size_t readSize = IoMessage_locals_intArgAt_(m, locals, 1);
329 if (Socket_streamRead(SOCKET(self), buffer, readSize))
331 return self;
333 else
335 if (Socket_asyncFailed())
337 IoSocket_close(self, locals, m);
338 return SOCKETERROR("Socket stream read failed");
340 else
342 if (SocketErrorStatus() == 0)
343 // 0 bytes means the other end disconnected
344 IoSocket_close(self, locals, m);
345 return IONIL(self);
350 IoObject *IoSocket_asyncStreamWrite(IoSocket *self, IoObject *locals, IoMessage *m)
352 IoSeq *bufferSeq = IoMessage_locals_seqArgAt_(m, locals, 0);
353 UArray *buffer = IoSeq_rawUArray(bufferSeq);
354 size_t start = IoMessage_locals_intArgAt_(m, locals, 1);
355 size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 2);
356 size_t bytesWritten = Socket_streamWrite(SOCKET(self), buffer, start, writeSize);
358 if (bytesWritten)
360 UArray_removeRange(buffer, start, bytesWritten);
361 return self;
363 else
365 if (Socket_asyncFailed())
367 IoSocket_close(self, locals, m);
368 return SOCKETERROR("Socket stream write failed");
370 else
372 if (IoSocket_errorNumber(self, locals, m) == 0)
373 // 0 bytes means the other end disconnected
374 IoSocket_close(self, locals, m);
375 return IONIL(self);
380 // udp ------------------------------
382 IoObject *IoSocket_udpRead(IoSocket *self, IoObject *locals, IoMessage *m)
384 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
385 UArray *buffer = IoSeq_rawUArray(IoMessage_locals_mutableSeqArgAt_(m, locals, 1));
386 size_t readSize = IoMessage_locals_sizetArgAt_(m, locals, 2);
388 if (Socket_udpRead(SOCKET(self), address, buffer, readSize))
390 return self;
392 else
394 if (Socket_asyncFailed())
395 return SOCKETERROR("Socket udp read failed");
396 else
397 return IONIL(self);
401 IoObject *IoSocket_udpWrite(IoSocket *self, IoObject *locals, IoMessage *m)
403 IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
404 UArray *buffer = IoSeq_rawUArray(IoMessage_locals_seqArgAt_(m, locals, 1));
405 size_t start = IoMessage_locals_intArgAt_(m, locals, 2);
406 size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 3);
407 size_t bytesWritten = Socket_udpWrite(SOCKET(self), address, buffer, start, writeSize);
409 if (bytesWritten)
411 if (bytesWritten < writeSize)
413 return SOCKETERROR("Socket udp write failed");
415 else
417 UArray_removeRange(buffer, start, bytesWritten);
418 return self;
421 else
423 if (Socket_asyncFailed())
424 return SOCKETERROR("Socket udp write failed");
425 else
426 return IONIL(self);
430 // ----------------------------------
432 IoObject *IoSocket_setSocketReadBufferSize(IoSocket *self, IoObject *locals, IoMessage *m)
434 int size = IoMessage_locals_intArgAt_(m, locals, 0);
435 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(int));
436 return IONUMBER(r);
439 IoObject *IoSocket_setSocketWriteBufferSize(IoSocket *self, IoObject *locals, IoMessage *m)
441 int size = IoMessage_locals_intArgAt_(m, locals, 0);
442 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int));
443 return IONUMBER(r);
446 IoObject *IoSocket_setSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
448 int size = IoMessage_locals_intArgAt_(m, locals, 0);
449 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, sizeof(int));
450 return IONUMBER(r);
453 IoObject *IoSocket_setSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
455 int size = IoMessage_locals_intArgAt_(m, locals, 0);
456 int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, sizeof(int));
457 return IONUMBER(r);
460 IoObject *IoSocket_getSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
462 int size = 0;
463 socklen_t length = sizeof(int);
464 //int r =
465 getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, &length);
467 return IONUMBER(size);
470 IoObject *IoSocket_getSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
472 int size = 0;
473 socklen_t length = sizeof(int);
474 //int r =
475 getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, &length);
476 return IONUMBER(size);
479 #ifndef WIN32
480 #include <sys/socket.h>
481 #endif
483 IoObject *IoSocket_setNoDelay(IoSocket *self, IoObject *locals, IoMessage *m)
485 int r = -1;
486 #ifdef TCP_NODELAY
487 int flag = 1;
488 r = setsockopt(SOCKET(self)->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
489 #endif
490 return IONUMBER(r);
493 IoObject *IoSocket_errorNumber(IoSocket *self, IoObject *locals, IoMessage *m)
495 return IONUMBER(SocketErrorStatus());
498 IoObject *IoSocket_errorDescription(IoSocket *self, IoObject *locals, IoMessage *m)
500 return IOSYMBOL(Socket_errorDescription());