28 |
28 |
29 return write(sock->fd, buf, len); |
29 return write(sock->fd, buf, len); |
30 } |
30 } |
31 |
31 |
32 /* |
32 /* |
33 * Define our sock_stream_Type |
33 * Our sock_stream_type |
|
34 * |
|
35 * XXX: move to sock_tcp.h |
34 */ |
36 */ |
35 struct sock_stream_type sock_tcp_type = { |
37 struct sock_stream_type sock_tcp_type = { |
36 .methods.read = &sock_tcp_read, |
38 .methods.read = &sock_tcp_read, |
37 .methods.write = &sock_tcp_write, |
39 .methods.write = &sock_tcp_write, |
38 }; |
40 }; |
39 |
41 |
40 struct sock_stream* sock_tcp_new (int fd) |
42 struct sock_tcp* sock_tcp_alloc (void) |
41 { |
43 { |
42 struct sock_tcp *sock; |
44 struct sock_tcp *sock; |
43 |
45 |
44 // alloc |
46 // alloc |
45 if ((sock = calloc(1, sizeof(*sock))) == NULL) |
47 if ((sock = calloc(1, sizeof(*sock))) == NULL) |
46 errx(1, "calloc"); |
48 errx(1, "calloc"); |
|
49 |
|
50 // initialize base |
|
51 sock->base.type = &sock_tcp_type; |
47 |
52 |
|
53 // done |
|
54 return sock; |
|
55 } |
|
56 |
|
57 int sock_tcp_init_fd (struct sock_tcp *sock, int fd) |
|
58 { |
48 // initialize |
59 // initialize |
49 sock->base.type = &sock_tcp_type; |
|
50 sock->fd = fd; |
60 sock->fd = fd; |
51 |
61 |
52 // done |
62 // done |
53 return SOCK_TCP_BASE(sock); |
63 return 0; |
54 } |
64 } |
55 |
65 |
56 struct sock_stream* sock_tcp_connect (const char *host, const char *service) |
66 int sock_tcp_init_connect (struct sock_tcp *sock, const char *hostname, const char *service) |
57 { |
67 { |
58 struct addrinfo hints, *res, *r; |
68 struct addrinfo hints, *res, *r; |
59 int _err, fd = -1; |
69 int _err; |
60 |
70 |
61 // hints |
71 // hints |
62 memset(&hints, 0, sizeof(hints)); |
72 memset(&hints, 0, sizeof(hints)); |
63 hints.ai_family = AF_UNSPEC; |
73 hints.ai_family = AF_UNSPEC; |
64 hints.ai_socktype = SOCK_STREAM; |
74 hints.ai_socktype = SOCK_STREAM; |
65 |
75 |
66 // resolve |
76 // resolve |
67 if ((_err = getaddrinfo(host, service, &hints, &res))) |
77 if ((_err = getaddrinfo(hostname, service, &hints, &res))) |
68 errx(1, "getaddrinfo: %s", gai_strerror(_err)); |
78 errx(1, "getaddrinfo: %s", gai_strerror(_err)); |
69 |
79 |
70 // use |
80 // use |
71 for (r = res; r; r = r->ai_next) { |
81 for (r = res; r; r = r->ai_next) { |
72 // XXX: wrong |
82 // XXX: wrong |
73 if ((fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) |
83 if ((sock->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0) |
74 err(1, "socket"); |
84 err(1, "socket"); |
75 |
85 |
76 if (connect(fd, r->ai_addr, r->ai_addrlen)) |
86 if (connect(sock->fd, r->ai_addr, r->ai_addrlen)) |
77 err(1, "connect"); |
87 err(1, "connect"); |
78 |
88 |
79 break; |
89 break; |
80 } |
90 } |
81 |
91 |
82 // ensure we got some valid socket |
92 // ensure we got some valid socket |
83 if (fd < 0) |
93 if (sock->fd < 0) |
84 errx(1, "no valid socket"); |
94 errx(1, "no valid socket"); |
85 |
95 |
86 // ok, return sock_stream |
96 // ok, done |
87 return sock_tcp_new(fd); |
97 return 0; |
88 } |
98 } |
89 |
99 |
|
100 // XXX: error handling |
|
101 struct sock_stream* sock_tcp_connect (const char *host, const char *service) |
|
102 { |
|
103 struct sock_tcp *sock; |
|
104 |
|
105 // allocate |
|
106 sock = sock_tcp_alloc(); |
|
107 |
|
108 // connect |
|
109 sock_tcp_init_connect(sock, host, service); |
|
110 |
|
111 // done |
|
112 return SOCK_TCP_BASE(sock); |
|
113 } |