00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static VALUE
00027 udp_init(int argc, VALUE *argv, VALUE sock)
00028 {
00029 VALUE arg;
00030 int family = AF_INET;
00031 int fd;
00032
00033 rb_secure(3);
00034 if (rb_scan_args(argc, argv, "01", &arg) == 1) {
00035 family = rsock_family_arg(arg);
00036 }
00037 fd = rsock_socket(family, SOCK_DGRAM, 0);
00038 if (fd < 0) {
00039 rb_sys_fail("socket(2) - udp");
00040 }
00041
00042 return rsock_init_sock(sock, fd);
00043 }
00044
00045 struct udp_arg
00046 {
00047 struct addrinfo *res;
00048 int fd;
00049 };
00050
00051 static VALUE
00052 udp_connect_internal(struct udp_arg *arg)
00053 {
00054 int fd = arg->fd;
00055 struct addrinfo *res;
00056
00057 for (res = arg->res; res; res = res->ai_next) {
00058 if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
00059 return Qtrue;
00060 }
00061 }
00062 return Qfalse;
00063 }
00064
00065 VALUE rsock_freeaddrinfo(struct addrinfo *addr);
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 static VALUE
00084 udp_connect(VALUE sock, VALUE host, VALUE port)
00085 {
00086 rb_io_t *fptr;
00087 struct udp_arg arg;
00088 VALUE ret;
00089
00090 rb_secure(3);
00091 arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00092 GetOpenFile(sock, fptr);
00093 arg.fd = fptr->fd;
00094 ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
00095 rsock_freeaddrinfo, (VALUE)arg.res);
00096 if (!ret) rb_sys_fail("connect(2)");
00097 return INT2FIX(0);
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static VALUE
00113 udp_bind(VALUE sock, VALUE host, VALUE port)
00114 {
00115 rb_io_t *fptr;
00116 struct addrinfo *res0, *res;
00117
00118 rb_secure(3);
00119 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00120 GetOpenFile(sock, fptr);
00121 for (res = res0; res; res = res->ai_next) {
00122 if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
00123 continue;
00124 }
00125 freeaddrinfo(res0);
00126 return INT2FIX(0);
00127 }
00128 freeaddrinfo(res0);
00129 rb_sys_fail("bind(2)");
00130 return INT2FIX(0);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 static VALUE
00156 udp_send(int argc, VALUE *argv, VALUE sock)
00157 {
00158 VALUE flags, host, port;
00159 rb_io_t *fptr;
00160 int n;
00161 struct addrinfo *res0, *res;
00162 struct rsock_send_arg arg;
00163
00164 if (argc == 2 || argc == 3) {
00165 return rsock_bsock_send(argc, argv, sock);
00166 }
00167 rb_secure(4);
00168 rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port);
00169
00170 StringValue(arg.mesg);
00171 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00172 GetOpenFile(sock, fptr);
00173 arg.fd = fptr->fd;
00174 arg.flags = NUM2INT(flags);
00175 for (res = res0; res; res = res->ai_next) {
00176 retry:
00177 arg.to = res->ai_addr;
00178 arg.tolen = res->ai_addrlen;
00179 rb_thread_fd_writable(arg.fd);
00180 n = (int)BLOCKING_REGION(rsock_sendto_blocking, &arg);
00181 if (n >= 0) {
00182 freeaddrinfo(res0);
00183 return INT2FIX(n);
00184 }
00185 if (rb_io_wait_writable(fptr->fd)) {
00186 goto retry;
00187 }
00188 }
00189 freeaddrinfo(res0);
00190 rb_sys_fail("sendto(2)");
00191 return INT2FIX(n);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 static VALUE
00244 udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
00245 {
00246 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
00247 }
00248
00249
00250
00251
00252
00253
00254 void
00255 rsock_init_udpsocket(void)
00256 {
00257 rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
00258 rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
00259 rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
00260 rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
00261 rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
00262 rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
00263 }
00264
00265