=================================================================== RCS file: /home/cvs/OpenXM/src/ox_toolkit/mysocket.c,v retrieving revision 1.1 retrieving revision 1.7 diff -u -p -r1.1 -r1.7 --- OpenXM/src/ox_toolkit/mysocket.c 1999/12/09 22:44:55 1.1 +++ OpenXM/src/ox_toolkit/mysocket.c 2003/01/11 11:42:31 1.7 @@ -1,10 +1,14 @@ /* -*- mode: C; coding: euc-japan -*- */ -/* $OpenXM$ */ -/* -setsockopt()してオプションを設定後, -socket, bind -するとローカルポートが割り当てられる。 -その後, getsockname によってポート番号が求まる. +/* $OpenXM: OpenXM/src/ox_toolkit/mysocket.c,v 1.6 2000/12/01 16:31:11 ohara Exp $ */ +/* +Q: How to get a local port number? +A: You do setsockopt() to set options and do socket(), bind(). +An OS set a local port for you. +In order to get the local port, you need to do getsockname(). +(See [1] pp. 91, pp. 187 for detail) + +Reference +[1] W. Richard Stevens, "UNIX Network Programming", 2nd ed. Vol. 1 (Japanese version) */ #include @@ -12,6 +16,7 @@ socket, bind #include #include #include +#include #include #include #include @@ -22,85 +27,102 @@ socket, bind #endif #include "mysocket.h" +#include "ox_toolkit.h" -static int getsocket(struct sockaddr_in *mp, char *host, short port) +typedef struct ox_sockopt { + int level; + int option_name; + void* option_value; + int option_len; +} ox_sockopt; + +static int getsocket(struct sockaddr_in *mp, char *host, int port) { struct hostent *ent = gethostbyname(host); - + memset(mp, '\0', sizeof(struct sockaddr_in)); mp->sin_family = AF_INET; - mp->sin_port = htons(port); + mp->sin_port = htons((short)port); memcpy((char *)&mp->sin_addr, ent->h_addr, ent->h_length); return socket(AF_INET, SOCK_STREAM, 0); } -int mysocketAccept(int s_waiting) +static int ox_connect(char *hostname, int port, ox_sockopt *opt) { - int val = accept(s_waiting, NULL, NULL); - return val; + struct sockaddr_in serv; + int s = getsocket(&serv, hostname, port); + if (connect(s, (struct sockaddr *)&serv, sizeof(serv)) != 0) { + fprintf(ox_stderr, "ox_connect: failed. socket = %d, errno = %d\n", s, errno); + return -1; + } + return s; } -int mysocketListen(char *hostname, short *portp) +static int ox_listen(char *hostname, int *port, int backlog, ox_sockopt *opt) { - int option; - int tmp; struct sockaddr_in me; - - int s_waiting = getsocket(&me, hostname, *portp); + int s_waiting = getsocket(&me, hostname, *port); - option = 1; - setsockopt(s_waiting, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); - - if (bind(s_waiting, (struct sockaddr *)&me, sizeof(me)) < 0) { - fprintf(stderr, "bind: failed.\n"); - exit(1); + setsockopt(s_waiting, opt->level, opt->option_name, + opt->option_value, opt->option_len); + if (bind(s_waiting, (struct sockaddr *)&me, sizeof(me)) < 0 + || listen(s_waiting, backlog) < 0) { + fprintf(ox_stderr, "ox_listen: failed.\n"); + return -1; } + return s_waiting; +} - tmp = sizeof(me); - if (getsockname(s_waiting, (struct sockaddr *)&me, &tmp) < 0) { - fprintf(stderr, "getsockname is failed.\n"); - exit(1); +static int ox_getport(int s_waiting) +{ + struct sockaddr_in me; + int len = sizeof(me); + if (getsockname(s_waiting, (struct sockaddr *)&me, &len) < 0) { + fprintf(ox_stderr, "ox_getport: failed.\n"); + return -1; } + return ntohs(me.sin_port); +} - *portp = ntohs(me.sin_port); - - if (listen(s_waiting, 1) < 0) { - fprintf(stderr, "listen: failed.\n"); - exit(1); - } - - return s_waiting; +int mysocketAccept(int s_waiting) +{ + /* return ox_accept(s_waiting); */ + return accept(s_waiting, NULL, NULL); } -int mysocketOpen(char* hostname, short port) +int mysocketListen(char *hostname, int *port) { - struct sockaddr_in serv; - int s = getsocket(&serv, hostname, port); + int option = 1; + ox_sockopt opt = {SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)}; + int s_waiting = ox_listen(hostname, port, 1, &opt); - fprintf(stderr, "get socket address for port number %d.\n", port); - if (connect(s, (struct sockaddr *)&serv, sizeof(serv)) != 0) { - fprintf(stderr, "connect: fail! socket = %d, errno = %d\n", s, errno); - exit(-1); + if (*port == 0) { + *port = ox_getport(s_waiting); } - return s; + return s_waiting; } +int mysocketOpen(char* hostname, int port) +{ + return ox_connect(hostname, port, NULL); +} + #if 0 int mypipe(char *program, int fd1, int fd2) { int sockfd[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) { - fprintf(stderr, "socketpair: fail! errno = %d\n", errno); + fprintf(ox_stderr, "socketpair: fail! errno = %d\n", errno); } if (fork() == 0) { - /* 子プロセス */ + /* child process */ close(sockfd[0]); dup2(sockfd[1], fd1); dup2(sockfd[1], fd2); execl(program, program, NULL); } - /* 親プロセス */ + /* parent process */ close(sockfd[1]); return sockfd[0]; }