⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_sock.c

📁 简单的基于SIP的会话边界控制器
💻 C
字号:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#include <osipparser2/osip_parser.h>

#include "nsrsbc.h"

/* socket used for sending SIP datagrams */
int sip_udp_socket = 0;


/*
 * binds to SIP UDP socket for listening to incoming packets
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int sipsock_listen (void) {

	struct in_addr ipaddr;

	/* Set IP address to INADDR_ANY, so the socket will recevie
	 * all packets from both eth0 and eht1.
	 */
	memset(&ipaddr, 0, sizeof(ipaddr));
	ipaddr.s_addr = htonl(INADDR_ANY);
	sip_udp_socket = sockbind(ipaddr, SIP_LISTENING_PORT);
	if (sip_udp_socket == 0) return STS_FAILURE;
	return STS_SUCCESS;
}

/*
 * Wait for incoming SIP message. After a 2 sec timeout
 * this function returns with sts=0
 *
 * RETURNS >0 if data received, =0 if nothing received /T/O), -1 on error
 *
 */
int sipsock_wait(void) {
	int sts;
	fd_set fdset;
	struct timeval timeout;

	timeout.tv_sec=2;
	timeout.tv_usec=0;

	FD_ZERO(&fdset);
	FD_SET (sip_udp_socket, &fdset);
	sts = select (sip_udp_socket+1, &fdset, NULL, NULL, &timeout);
	
	/* WARN on failures */
	if (sts < 0) {
		/* WARN on failure, except if it is an "interrupted system call"
		 * as it will result by SIGINT, SIGTERM 
		 */
		if (errno != 4) {
			printf("sipsock: select() returned error [%i:%s]\n",errno, strerror(errno));
		} else {
			printf("sipsock: select() returned error [%i:%s]\n", errno, strerror(errno));
		}
	}

	return sts;
}

/*
 * Read a message from SIP listen socket (UDP datagram)
 *
 * RETURNS number of bytes read
 *         from is modified to return the sockaddr_in of the sender
 *
 */
int sipsock_read(void *buf, size_t bufsize, struct sockaddr_in *from, int *protocol) {
	int count;
	socklen_t fromlen;

	fromlen = sizeof(struct sockaddr_in);
	*protocol = PROTO_UDP; /* up to now, unly UDP, TCP later */
	count = recvfrom(sip_udp_socket, buf, bufsize, 0, (struct sockaddr *)from, &fromlen);

	if (count<0) {
		printf("sipsock: recvfrom() returned error [%s]\n",strerror(errno));
		*protocol = PROTO_UNKN;
	}

	printf("sipsock: received UDP packet from %s, count=%i\n", inet_ntoa(from->sin_addr), count);

	return count;
}


/*
 * Sends an UDP datagram to the specified destination
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 *
 */
int sipsock_send(struct in_addr addr, int port, int protocol, char *buffer, size_t size) {
	struct sockaddr_in dst_addr;
	int sts;

	/* first time: allocate a socket for sending */
	if (sip_udp_socket == 0) {
		printf("sipsock: SIP socket not allocated!\n");
		return STS_FAILURE;
	}

	if (buffer == NULL) {
		printf("sipsock: sipsock_send got NULL buffer!\n");
		return STS_FAILURE;
	}

	if (protocol != PROTO_UDP) {
		printf("sipsock: sipsock_send: only UDP supported by now!\n");
		return STS_FAILURE;
	}

	dst_addr.sin_family = AF_INET;
	memcpy(&dst_addr.sin_addr.s_addr, &addr, sizeof(struct in_addr));
	dst_addr.sin_port= htons(port);

	sts = sendto(sip_udp_socket, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr));

	if (sts == -1) {
		if (errno != ECONNREFUSED) {
			printf("sipsock: sendto() [%s:%i size=%ld] call failed: %s\n", inet_ntoa(addr), port, (long)size, strerror(errno));
         		return STS_FAILURE;
      		}
      		printf("sipsock: sendto() [%s:%i] call failed: %s\n", inet_ntoa(addr), port, strerror(errno));
   	}

	return STS_SUCCESS;
}



/*
 * generic routine to allocate and bind a socket to a specified
 * local address and port (UDP)
 *
 * RETURNS
 *	socket fd number on success
 *	zero on failure
 *
 */
int sockbind(struct in_addr ipaddr, int localport) {
	struct sockaddr_in my_addr;
	int sts, on=1;
	int sock;
	int flags;

	//printf("sock bind start!\n");
	memset(&my_addr, 0, sizeof(my_addr));

	my_addr.sin_family = AF_INET;
	memcpy(&my_addr.sin_addr.s_addr, &ipaddr, sizeof(struct in_addr));
	my_addr.sin_port = htons(localport);

	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (sock < 0) {
		printf("sipsock: socket call failed: %s\n",strerror(errno));
		return 0;
	}

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on , sizeof(on)) < 0) {
		printf("sipsock: setsockopt returned error [%i:%s]\n",errno, strerror(errno));
		return 0;
	}

	sts = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
	if (sts != 0) {
		printf("sipsock: bind failed: %s\n",strerror(errno));
		close(sock);
		return 0;
	}

	flags = fcntl(sock, F_GETFL);
	if (flags < 0) {
		printf("sipsock: fcntl(F_SETFL) failed: %s\n",strerror(errno));
		close(sock);
		return 0;
	}
	if (fcntl(sock, F_SETFL, (long) flags | O_NONBLOCK) < 0) {
		printf("sipsock: fcntl(F_SETFL) failed: %s\n",strerror(errno));
		close(sock);
		return 0;
	}

	return sock;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -