PageRenderTime 31ms CodeModel.GetById 1ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/addons/Socket/source/IoSocket.c

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