int MakeApiSocket(int transport_type) { struct sockaddr_in sa; int sock; unsigned short port; socklen_t len = sizeof(sa); if ((sock = (_f_socket)(AF_INET, SOCK_DGRAM, 0)) == -1) { LOGF("Error creating socket: %s", strerror(errno)); return sock; } // bind to an unused random port number sa.sin_family = PF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = 0; if ((_f_bind)(sock, (const struct sockaddr *)&sa, sizeof(sa)) < 0) { (_f_close)(sock); LOGF("Error binding new socket to local port: %s", strerror(errno)); return -1; } if((_f_getsockname)(sock, (struct sockaddr *)&sa, &len) < 0) { LOGF("Error retrieving socket's UDP port: %s", strerror(errno)); port = 0; } else { port = ((struct sockaddr_in)sa).sin_port; } allocSocketState(sock, transport_type, port); return sock; }
/*! ** @brief Create an XIA socket ** ** Creates an XIA socket of the specified type. ** ** @param family socket family, currently must be AF_XIA ** @param transport_type Valid values are: ** \n SOCK_STREAM for reliable communications (SID) ** \n SOCK_DGRAM for a ligher weight connection, but with ** unguranteed delivery (SID) ** \n XSOCK_CHUNK for getting/putting content chunks (CID) ** \n SOCK_RAW for a raw socket that can have direct edits made to the header ** @param for posix compatibility, currently must be 0 ** ** @returns socket id on success. ** @returns -1 on failure with errno set to an error compatible with those ** from the standard socket call. ** ** @warning In the current implementation, the returned socket is ** a normal UDP socket that is used to communicate with the click ** transport layer. Using this socket with normal unix socket ** calls (aside from select and poll) will cause unexpected behaviors. ** Attempting to pass a socket created with the the standard socket function ** to the Xsocket API will have similar results. ** */ int Xsocket(int family, int transport_type, int protocol) { struct sockaddr_in addr; xia::XSocketCallType type; int rc; int sockfd; if (family != AF_XIA) { LOG("error: the Xsockets API only supports the AF_XIA family"); errno = EAFNOSUPPORT; return -1; } if (protocol != 0) { LOG("error: the protocol field is not currently used in the Xsocket API"); errno = EINVAL; return -1; } /*if (transport_type & SOCK_NONBLOCK || transport_type & SOCK_CLOEXEC) { LOG("error: invalid flags passed as part of the treansport_type"); errno = EINVAL; return -1; }*/ switch (transport_type) { case SOCK_STREAM: case SOCK_DGRAM: case XSOCK_CHUNK: case SOCK_RAW: break; default: // invalid socket type requested LOG("error: invalid transport_type specified"); errno = EINVAL; return -1; } if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { LOGF("error creating Xsocket: %s", strerror(errno)); return -1; } // bind to any random port number addr.sin_family = PF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = 0; // protobuf message xia::XSocketMsg xsm; xsm.set_type(xia::XSOCKET); xia::X_Socket_Msg *x_socket_msg = xsm.mutable_x_socket(); x_socket_msg->set_type(transport_type); if ((rc = click_send(sockfd, &xsm)) < 0) { LOGF("Error talking to Click: %s", strerror(errno)); close(sockfd); return -1; } // process the reply from click if ((rc = click_reply2(sockfd, &type)) < 0) { LOGF("Error getting status from Click: %s", strerror(errno)); } else if (type != xia::XSOCKET) { // something bad happened LOGF("Expected type %d, got %d", xia::XSOCKET, type); errno = ECLICKCONTROL; rc = -1; } if (rc == 0) { allocSocketState(sockfd, transport_type); return sockfd; } // close the control socket since the underlying Xsocket is no good close(sockfd); return -1; }