root/lang/cplusplus/llv8call/branches/unixsocket/ext/socket/socket.cc @ 21243

Revision 21243, 14.0 kB (checked in by tokuhirom, 5 years ago)

fixed some problems

Line 
1// The MIT License
2//
3// Copyright (c) 2008 Tokuhiro Matsuno
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21// THE SOFTWARE.
22
23#include <v8.h>
24#include <cstdio>
25#include <cstdlib>
26#include <memory.h>
27#include <errno.h>
28#include "v8ext.h"
29#include <llv8-macros.h>
30#ifndef _WIN32
31#  include <sys/socket.h>
32#  include <sys/types.h>
33#  include <netinet/in.h>
34#  include <arpa/inet.h>
35#  include <sys/un.h>
36#  include <unistd.h>
37#  include <sys/param.h>
38#  include <netdb.h>
39#endif
40
41typedef union sock_addr {
42    struct sockaddr_in in;
43#ifdef AF_UNIX
44    struct sockaddr_un un;
45#endif
46} sock_addr_t;
47
48/** DESCRIPTION:
49 *
50 * low level socket class.
51 *
52 * Design of this class is inspired from python's socket class.
53 *
54 */
55
56#define EXTERNAL_SOCKET() int sock = (int) args.This()->GetInternalField(0)->Int32Value()
57
58using namespace v8;
59
60static inline Handle<Value> throw_stderr(const char *msg) {
61    std::string buf(msg);
62    buf += " error: ";
63    buf += strerror(errno);
64    return ThrowException(String::New(buf.c_str()));
65}
66
67static inline v8::Handle<v8::Object> socket_namespace() {
68        return v8::Context::GetCurrent()->Global()
69                      ->Get(v8::String::New("org"))->ToObject()
70                      ->Get(v8::String::New("coderepos"))->ToObject()
71                      ->Get(v8::String::New("socket"))->ToObject();
72}
73
74// TODO: support AF_UNIX
75static inline Handle<Array> _makeaddr(sockaddr & addr) {
76    Handle<Array> ret = Array::New(2);
77    switch (addr.sa_family) {
78#if defined(AF_UNIX)
79    case AF_UNIX:
80        {
81            sockaddr_un * addr_un = (sockaddr_un*)&addr;
82            ret->Set(Int32::New(0), String::New(addr_un->sun_path));
83        }
84        break;
85#endif
86    case AF_INET:
87        {
88            char buf[NI_MAXHOST];
89            if (getnameinfo(&addr, sizeof(sockaddr_in), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST)) {
90                throw_stderr(__func__);
91                return ret;
92            }
93            sockaddr_in * addr_in = (sockaddr_in*)&addr;
94            ret->Set(Int32::New(0), String::New(buf));
95            ret->Set(Int32::New(1), Int32::New(ntohs(addr_in->sin_port)));
96        }
97        break;
98    default:
99        ThrowException(String::New("This family does not supported yet"));
100        return ret;
101    }
102    return ret;
103}
104
105// TODO: support unix domain socket
106// TODO: support inet6
107static inline void _gen_sockaddr(Handle<Array> &args, int family, sock_addr_t* addr_ret, socklen_t * len) {
108    switch (family) {
109#if defined(AF_UNIX)
110    case AF_UNIX:
111        {
112            puts("AF_UNIX");
113            if (args->Length() != 1) {
114                ThrowException(String::New("invalid args: AF_UNIX => (socket file)"));
115                return;
116            }
117            struct sockaddr_un *addr = (struct sockaddr_un*)addr_ret;
118            memset(addr, 0, sizeof(sockaddr_un)); // clear
119
120            String::Utf8Value path(args->Get(Int32::New(0)));
121            if ((unsigned int)path.length() >= sizeof(addr->sun_path)) {
122                ThrowException(String::New("path too long"));
123                return;
124            }
125            addr->sun_family = AF_UNIX;
126            memcpy(addr->sun_path, *path, path.length());
127            addr->sun_path[path.length()] = '\0';
128            puts(addr->sun_path);
129            *len = path.length() + (sizeof(*addr) - sizeof(addr->sun_path));
130        }
131        break;
132#endif
133    case AF_INET:
134        {
135            if (args->Length() != 2) {
136                ThrowException(String::New("invalid args: AF_INET => (host, port)"));
137                return;
138            }
139            String::Utf8Value host(args->Get(Int32::New(0)));
140            int32_t port = args->Get(Int32::New(1))->Int32Value();
141
142            struct sockaddr_in *addr = (struct sockaddr_in*)addr_ret;
143            memset(addr, 0, sizeof(*addr)); // clear
144            addr->sin_family = AF_INET;
145            in_addr_t hostinfo = inet_addr(*host);
146            if (hostinfo == INADDR_NONE) {
147                ThrowException(String::New("invalid ip"));
148                return;
149            }
150            addr->sin_addr.s_addr = hostinfo;
151            addr->sin_port = htons((short)port);
152            *len = sizeof(*addr);
153        }
154        break;
155    default:
156        fprintf(stderr, "unknown family");
157        abort();
158    }
159}
160
161
162FUNCTION(_open)
163    // USAGE: new Socket(Socket.AF_INET, Socket.SOCK_STREAM)
164    if (args.Length() == 2 && args[0]->IsExternal()) {
165        args.This()->SetInternalField(0, args[1]);
166        args.This()->Set(String::New("family"), args[2]);
167        args.This()->Set(String::New("type"),   args[3]);
168        args.This()->Set(String::New("proto"),  args[4]);
169        return args.This();
170    } else {
171        ARG_BETWEEN(0, 3);
172        ARG_int(family, 0);
173        ARG_int(type,   1);
174        ARG_int(protocol,  2);
175
176        if (args.Length() < 1) {
177            family = AF_INET;
178        }
179        if (args.Length() < 2) {
180            type = SOCK_STREAM;
181        }
182        if (args.Length() < 3) {
183            protocol = 0;
184        }
185
186        int desc = socket(family, type, protocol);
187        if (desc != -1) {
188            args.This()->SetInternalField(0, Int32::New(desc));
189            args.This()->Set(String::New("family"), Int32::New(family));
190            args.This()->Set(String::New("type"),   Int32::New(type));
191            args.This()->Set(String::New("proto"),  Int32::New(protocol));
192            return args.This();
193        } else {
194            return ThrowException(String::New("cannot open socket"));
195        }
196    }
197END
198
199FUNCTION(_bind)
200    EXTERNAL_SOCKET();
201    sock_addr_t addr;
202    socklen_t len;
203    int family = args.This()->Get(String::New("family"))->Int32Value();
204    ARG_array(addrsrc, 0);
205    printf("BIND: %d\n", sock);
206    _gen_sockaddr(addrsrc, family, &addr, &len);
207    printf("BIND: %d\n", sock);
208    printf("HEY: %d, %d, %d, %s\n", addr.un.sun_family, AF_UNIX, AF_INET, addr.un.sun_path);
209    if (bind(sock, (sockaddr*)&addr, len) == 0) {
210        return Undefined();
211    } else {
212        return throw_stderr("bind error: ");
213    }
214END
215
216FUNCTION(_listen)
217    EXTERNAL_SOCKET();
218    ARG_COUNT(1);
219    ARG_int(backlog, 0);
220    if (listen(sock, backlog) == 0) {
221        return Undefined();
222    } else {
223        return throw_stderr("listen error: ");
224    }
225END
226
227FUNCTION(_gethostname)
228    ARG_COUNT(0);
229    char * buf = new char [_POSIX_HOST_NAME_MAX+1];
230    if (gethostname(buf, _POSIX_HOST_NAME_MAX) == 0) {
231        Handle<String> str = String::New(buf);
232        delete [] buf;
233        return str;
234    } else {
235        delete [] buf;
236        return throw_stderr("gethostname error: ");
237    }
238END
239
240FUNCTION(_accept)
241    EXTERNAL_SOCKET();
242    ARG_COUNT(0);
243    struct sockaddr addr;
244    socklen_t len = sizeof(addr);
245    int newsock = accept(sock, &addr, &len);
246    if (newsock >= 0) {
247        Handle<Value> argv[2];
248        argv[0] = External::New(&len);
249        argv[1] = Int32::New(newsock);
250        argv[2] = args.This()->Get(String::New("family"));
251        argv[3] = args.This()->Get(String::New("type"));
252        argv[4] = args.This()->Get(String::New("proto"));
253        return Handle<Function>::Cast( socket_namespace()->Get(String::New("Socket")) )->NewInstance(2, argv);
254    } else {
255        return throw_stderr("accept error: ");
256    }
257END
258
259FUNCTION(_connect)
260    EXTERNAL_SOCKET();
261    sock_addr_t addr;
262    socklen_t len;
263    int family = args.This()->Get(String::New("family"))->Int32Value();
264    ARG_array(addrsrc, 0);
265    _gen_sockaddr(addrsrc, family, &addr, &len);
266    printf("connect: FAMILY: %d, %d, %s, %d\n", family, len, addr.un.sun_path, addr.un.sun_family);
267    if (connect(sock, (sockaddr*)&addr, len) == 0) {
268        return Undefined();
269    } else {
270        return throw_stderr("connect error: ");
271    }
272END
273
274FUNCTION(_recv)
275    EXTERNAL_SOCKET();
276    ARG_BETWEEN(1, 2);
277    ARG_int(len, 0);
278    int _flags = 0;
279    if (args.Length() == 2) {
280        ARG_int(flags, 1);
281        _flags = flags;
282    }
283    char * buf = new char [len+1];
284    assert(sock);
285    printf("FOOEEE %d, %d, %d\n", sock, len, _flags);
286    ssize_t size = recv(sock, buf, len, _flags);
287    if (size >= 0) {
288        Handle<String> res = String::New(buf, size);
289        delete [] buf;
290        return res;
291    } else {
292        delete [] buf;
293        return throw_stderr("recv error: ");
294    }
295END
296
297FUNCTION(_recvfrom)
298    EXTERNAL_SOCKET();
299    ARG_BETWEEN(1, 2);
300    ARG_int(buflen, 0);
301    int _flags = 0;
302    if (args.Length() == 2) {
303        ARG_int(flags, 1);
304        _flags = flags;
305    }
306    char * buf = new char [buflen];
307    struct sockaddr addr;
308    socklen_t addrlen = sizeof(sockaddr);
309    ssize_t size = recvfrom(sock, buf, buflen, _flags, &addr, &addrlen);
310    if (size >= 0) {
311        Handle<Array> ret = Array::New(2);
312        ret->Set(Int32::New(0), String::New(buf, size));
313        ret->Set(Int32::New(1), _makeaddr(addr));
314        delete [] buf;
315        return ret;
316    } else {
317        delete [] buf;
318        return throw_stderr("recvfrom error: ");
319    }
320END
321
322FUNCTION(_send)
323    // @ret Returns the number of bytes sent.
324    EXTERNAL_SOCKET();
325    ARG_BETWEEN(1, 2);
326    ARG_str(str, 0);
327    int _flags = 0;
328    if (args.Length() == 2) {
329        ARG_int(flags, 1);
330        _flags = flags;
331    }
332    ssize_t size = send(sock, *str, str.length(), _flags);
333    if (size >= 0) {
334        return Int32::New(size);
335    } else {
336        return throw_stderr("send error: ");
337    }
338END
339
340FUNCTION(_sendto)
341    // @prototype sock.sendto(str, [flags, ] addr);
342    // @ret Returns the number of bytes sent.
343    EXTERNAL_SOCKET();
344    ARG_BETWEEN(2, 3);
345    ARG_str(str, 0);
346    int _flags = 0;
347    Handle<Array> addrsrc;
348    if (args.Length() == 3) {
349        ARG_int(flags, 1);
350        _flags = flags;
351        addrsrc = Handle<Array>::Cast(args[2]);
352    } else {
353        addrsrc = Handle<Array>::Cast(args[1]);
354    }
355    sock_addr_t addr;
356    socklen_t len;
357    int family = args.This()->Get(String::New("family"))->Int32Value();
358    _gen_sockaddr(addrsrc, family, &addr, &len);
359    ssize_t size = sendto(sock, *str, str.length(), _flags, (sockaddr*)&addr, len);
360    if (size >= 0) {
361        return Int32::New(size);
362    } else {
363        return throw_stderr("send error: ");
364    }
365END
366
367FUNCTION(_getsockname)
368    EXTERNAL_SOCKET();
369    ARG_COUNT(0);
370    sockaddr addr;
371    socklen_t len = sizeof(sockaddr);
372    if (getsockname(sock, &addr, &len) == 0) {
373        return _makeaddr(addr);
374    } else {
375        return throw_stderr("getsockname");
376    }
377END
378
379FUNCTION(_getpeername)
380    EXTERNAL_SOCKET();
381    ARG_COUNT(0);
382    sockaddr addr;
383    socklen_t len = sizeof(sockaddr);
384    if (getpeername(sock, &addr, &len) == 0) {
385        return _makeaddr(addr);
386    } else {
387        return throw_stderr("getpeername");
388    }
389END
390
391FUNCTION(_fileno)
392    EXTERNAL_SOCKET();
393    ARG_COUNT(0);
394    return Uint32::New(sock);
395END
396
397FUNCTION(_close)
398    EXTERNAL_SOCKET();
399    ARG_COUNT(0);
400    if (close(sock) >= 0) {
401        return Undefined();
402    } else {
403        return throw_stderr("close error: ");
404    }
405END
406
407FUNCTION(_inet_aton)
408    ARG_COUNT(1);
409    ARG_str(ip, 0);
410    in_addr addr;
411    if (inet_aton(*ip, &addr) == 1) {
412        return Uint32::New(addr.s_addr);
413    } else {
414        return throw_stderr("inet_aton");
415    }
416END
417
418FUNCTION(_inet_ntoa)
419    ARG_COUNT(1);
420    ARG_uint(ip, 0);
421    in_addr addr;
422    addr.s_addr = ip;
423    char * buf = inet_ntoa(addr);
424    if (buf) {
425        return String::New(buf);
426    } else {
427        return throw_stderr("inet_ntoa");
428    }
429END
430
431MODULE()
432    {
433        CLASS_WITH_CONSTRUCTOR(_open);
434
435        BIND_CI("SOCK_STREAM",    SOCK_STREAM);
436        BIND_CI("SOCK_DGRAM",     SOCK_DGRAM);
437        BIND_CI("SOCK_RAW",       SOCK_RAW);
438        BIND_CI("SOCK_RDM",       SOCK_RDM);
439        BIND_CI("SOCK_SEQPACKET", SOCK_SEQPACKET);
440
441#if defined(AF_UNIX)
442        BIND_CI("AF_UNIX",        AF_UNIX);
443#endif
444        BIND_CI("AF_INET",        AF_INET);
445        BIND_CI("AF_INET6",       AF_INET6);
446
447        BIND_CM("gethostname",    _gethostname);
448        BIND_CM("inet_aton",      _inet_aton);
449        BIND_CM("inet_ntoa",      _inet_ntoa);
450
451        BIND_IM("bind",           _bind);
452        BIND_IM("listen",         _listen);
453        BIND_IM("accept",         _accept);
454        BIND_IM("connect",        _connect);
455        BIND_IM("recv",           _recv);
456        BIND_IM("recvfrom",       _recvfrom);
457        BIND_IM("send",           _send);
458        BIND_IM("sendto",         _sendto);
459        BIND_IM("getsockname",    _getsockname);
460        BIND_IM("getpeername",    _getpeername);
461        BIND_IM("fileno",         _fileno);
462        BIND_IM("close",          _close);
463        // rest function is: 29
464        // getaddrinfo
465        // getfqdn
466        // gethostbyname
467        // gethostbyaddr
468        // getnameinfo
469        // getprotobyname
470        // getservbyname
471        // getservbyport
472        // socketpair
473        // fromfd
474        // ntohl
475        // ntohs
476        // htonl
477        // htons
478        // inet_pton
479        // inet_ntop
480        // getdefaulttimeout
481        // setdefaulttimeout
482        // getsockopt
483        // ioctl
484        // makefile
485        // recvfrom_into
486        // recv_into
487        // sendall
488        // setblocking
489        // settimeout
490        // gettimeout
491        // setsockopt
492        // shutdown
493
494        INTERNALCOUNT(1);
495
496        EXPORT_CLASS("Socket");
497    }
498ENDMODULE
499
Note: See TracBrowser for help on using the browser.