upscheme/c/socket.c

219 lines
5.2 KiB
C
Raw Normal View History

#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <assert.h>
#include <errno.h>
2008-06-30 21:53:51 -04:00
#include <stdio.h>
#include <stdlib.h>
2008-06-30 21:53:51 -04:00
#include <string.h>
#include <unistd.h>
#include "dtypes.h"
2008-06-30 21:53:51 -04:00
#include "socket.h"
int mysocket(int domain, int type, int protocol)
{
int val;
int s = socket(domain, type, protocol);
if (s < 0)
return s;
val = 4096;
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(int));
2008-06-30 21:53:51 -04:00
val = 4096;
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&val, sizeof(int));
2008-06-30 21:53:51 -04:00
return s;
}
2011-04-10 23:24:30 -04:00
void set_nonblock(int socket, int yes)
{
int flags;
flags = fcntl(socket, F_GETFL, 0);
2011-04-10 23:24:30 -04:00
assert(flags != -1);
if (yes)
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
else
fcntl(socket, F_SETFL, flags & ~O_NONBLOCK);
}
2008-06-30 21:53:51 -04:00
/* returns a socket on which to accept() connections */
int open_tcp_port(short portno)
{
int sockfd;
struct sockaddr_in serv_addr;
sockfd = mysocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0)
return -1;
memset(&serv_addr, 0, sizeof(serv_addr));
2008-06-30 21:53:51 -04:00
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
2008-06-30 21:53:51 -04:00
return -1;
}
listen(sockfd, 4);
return sockfd;
}
/* returns a socket on which to accept() connections, finding some
available port (portno is value-return) */
int open_any_tcp_port(short *portno)
{
int sockfd;
struct sockaddr_in serv_addr;
sockfd = mysocket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0)
return -1;
memset(&serv_addr, 0, sizeof(serv_addr));
2008-06-30 21:53:51 -04:00
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(*portno);
while (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) <
0) {
2008-06-30 21:53:51 -04:00
(*portno)++;
serv_addr.sin_port = htons(*portno);
}
listen(sockfd, 4);
return sockfd;
}
/* returns a socket on which to accept() connections, finding some
available port (portno is value-return) */
int open_any_udp_port(short *portno)
{
int sockfd;
struct sockaddr_in serv_addr;
2011-04-10 23:24:30 -04:00
sockfd = mysocket(PF_INET, SOCK_DGRAM, 0);
2008-06-30 21:53:51 -04:00
if (sockfd < 0)
return -1;
memset(&serv_addr, 0, sizeof(serv_addr));
2008-06-30 21:53:51 -04:00
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(*portno);
while (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) <
0) {
2008-06-30 21:53:51 -04:00
(*portno)++;
serv_addr.sin_port = htons(*portno);
}
return sockfd;
}
#ifndef WIN32
void closesocket(int fd) { close(fd); }
2008-06-30 21:53:51 -04:00
#endif
/* returns a socket to use to send data to the given address */
int connect_to_host(char *hostname, short portno)
{
struct hostent *host_info;
int sockfd, yes = 1;
2008-06-30 21:53:51 -04:00
struct sockaddr_in host_addr;
host_info = gethostbyname(hostname);
if (host_info == NULL) {
return -1;
}
sockfd = mysocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
return -1;
}
(void)setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
memset((char *)&host_addr, 0, sizeof(host_addr));
2008-06-30 21:53:51 -04:00
host_addr.sin_family = host_info->h_addrtype;
memcpy((char *)&host_addr.sin_addr, host_info->h_addr,
2008-06-30 21:53:51 -04:00
host_info->h_length);
host_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *)&host_addr,
2008-06-30 21:53:51 -04:00
sizeof(struct sockaddr_in)) != 0) {
closesocket(sockfd);
return -1;
}
return sockfd;
}
int connect_to_addr(struct sockaddr_in *host_addr)
{
int sockfd, yes = 1;
2008-06-30 21:53:51 -04:00
sockfd = mysocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
return -1;
}
(void)setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (connect(sockfd, (struct sockaddr *)host_addr,
2008-06-30 21:53:51 -04:00
sizeof(struct sockaddr_in)) != 0) {
closesocket(sockfd);
return -1;
}
return sockfd;
}
/* repeated send until all of buffer is sent */
int sendall(int sockfd, char *buffer, int bufLen, int flags)
{
int numBytesToSend = bufLen, length;
2008-06-30 21:53:51 -04:00
while (numBytesToSend > 0) {
length = send(sockfd, (void *)buffer, numBytesToSend, flags);
2008-06-30 21:53:51 -04:00
if (length < 0) {
return (-1);
2008-06-30 21:53:51 -04:00
}
numBytesToSend -= length;
buffer += length;
2008-06-30 21:53:51 -04:00
}
return (bufLen);
2008-06-30 21:53:51 -04:00
}
/* repeated read until all of buffer is read */
int readall(int sockfd, char *buffer, int bufLen, int flags)
{
int numBytesToRead = bufLen, length;
2008-06-30 21:53:51 -04:00
while (numBytesToRead > 0) {
2008-06-30 21:53:51 -04:00
length = recv(sockfd, buffer, numBytesToRead, flags);
if (length <= 0) {
return (length);
2008-06-30 21:53:51 -04:00
}
numBytesToRead -= length;
buffer += length;
}
return (bufLen);
2008-06-30 21:53:51 -04:00
}
int addr_eq(struct sockaddr_in *a, struct sockaddr_in *b)
{
if (a->sin_port == b->sin_port &&
a->sin_addr.s_addr == b->sin_addr.s_addr)
return 1;
return 0;
}
int socket_ready(int sock)
{
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 1000;
FD_ZERO(&fds);
FD_SET(sock, &fds);
select(sock + 1, &fds, NULL, NULL, &timeout);
2008-06-30 21:53:51 -04:00
return FD_ISSET(sock, &fds);
}