Very rough first start, not even everything added

This commit is contained in:
Darren VanBuren 2017-03-07 14:51:44 -08:00
commit af3619d4fa
88 changed files with 24251 additions and 0 deletions

View file

@ -0,0 +1,154 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* get_opt.c
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#if defined(mac)
#include <types.h>
#endif
int get_opt(int argc, char *argv[], char *optList);
char *optarg = NULL;
char *whatOption = NULL;
int currentOpt = 0;
int optind = 1;
extern char gOptionsChar;
/* compareOptionString takes an option parameter with the following format:
* -REQuired : the characters in CAPS are required to match.
*/
static int compareOptionString(char *option, char *compareit) {
int i, l1, l2;
l1 = strlen(option);
l2 = strlen(compareit);
for (i=0; i<l2; i++) {
if (option[i] == '\0')
return -1; /* option < compareit */
if (tolower(option[i]) == tolower(compareit[i])) {
}
else {
if (option[i] > compareit[i])
return 1; /* option > compareit */
else
return -1; /* option < compareit */
}
}
/* if we got here, all of the characters in compareit are in option. */
/* now we've got to check if there are any more required characters. */
if (l1 > l2) { /* only need to check if option is longer than compareit */
if (option[l2] == toupper(option[l2]))
return 1; /* there was an additional character[s] needed. */
}
/* if we got here, then all is hunky dory and we got the required stuff. */
return 0;
}
int get_opt(int argc, char *argv[], char *optList) {
char option[256];
int l, i, c, opt;
currentOpt = optind;
optind++;
if (currentOpt >= argc) {
return EOF;
}
optarg = NULL;
whatOption = argv[currentOpt];
if (whatOption[0] != gOptionsChar) {
optarg = whatOption;
return 0;
}
l = strlen(optList);
i = 1;
c = 0;
opt = 1;
option[c++] = gOptionsChar;
while (i<=l) {
if (optList[i] == gOptionsChar) {
option[c++] = '\0';
// if (strncasecmp(option, whatOption, strlen(whatOption)) == 0)
if (compareOptionString(option, whatOption) == 0)
// return opt;
return option[1];
c = 1; // reset option string to '-' since we've just seen it
opt++; // check next option
}
else if (optList[i] == ':') {
option[c++] = '\0';
// if (strncasecmp(option, whatOption, strlen(whatOption)) == 0) {
if (compareOptionString(option, whatOption) == 0) {
currentOpt++; optind++;
optarg = argv[currentOpt];
// return opt;
return option[1];
}
c = 1; // reset option string to '-'
opt++; // check next option
i++; // pass over the :
if (optList[i] == gOptionsChar) {
; // this is where we want to be
}
else if (optList[i] == '\0') {
// return EOF; // this was the last option to check
return 0; // this was the last option to check
}
else {
fprintf(stderr, "Malformed getopt string '%s': character %d is '%c' was expecting %c\n", optList, i, optList[i], gOptionsChar);
return 0;
}
}
else if (optList[i] == '\0') {
option[c++] = '\0';
// if (strncasecmp(option, whatOption, strlen(whatOption)) == 0) {
if (compareOptionString(option, whatOption) == 0) {
// return opt;
return option[1];
}
optarg = argv[currentOpt];
// return EOF; // didn't find anything, return EOF
return 0; // didn't find anything, return EOF
}
else {
option[c++] = optList[i];
}
i++;
}
optarg = argv[currentOpt];
return 0;
}

View file

@ -0,0 +1,42 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* get_opt.h
*
*/
#ifndef __GETOPT_H__
#define __GETOPT_H__
extern char *optarg;
extern char *whatOption;
extern int currentOpt;
extern int optind;
int get_opt(int argc, char *argv[], char *optList);
#endif

1983
StreamingProxy.tproj/proxy.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,167 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* proxy.h
*
*
*/
#ifndef __PROXY_H__
#define __PROXY_H__
#include "shared_udp.h"
/**********************************************/
enum {
stIdle,
stError,
stRecvClientCommand,
stWaitingForIPAddress,
stParseClientCommand,
stSendClientResponse,
stServerTransactionSend,
stServerTransactionRecv,
stClientShutdown,
stServerShutdown,
stBadServerName,
stCantConnectToServer,
stDone
}; // rtsp session states
enum {
ttNone,
ttDescribe,
ttSetup,
ttPlay,
ttPause,
ttStop,
ttTeardown,
ttOptions,
ttAnnounce,
ttRedirect,
ttGetParameter,
ttSetParameter
}; // rtsp command types
enum {
kPermissionDenied,
kTooManyUsers,
kServerNotFound,
kUnknownError
}; // refusal type
typedef struct {
char *cmd;
int type;
} t_cmd_map;
#define MAX_TRACKS 32
typedef struct {
int ID;
shok *RTP_S2P;
shok *RTCP_S2P;
shok *RTP_P2C;
shok *RTCP_P2C;
int ClientRTPPort;
int ServerRTPPort;
trans_pb RTP_S2C_tpb;
trans_pb RTCP_S2C_tpb;
trans_pb RTCP_C2S_tpb;
} track_info;
/* This size will fit nicely in a standard ethernet frame */
#define RTSP_SESSION_BUF_SIZE 4096
typedef struct rtsp_session {
struct rtsp_session *next;
int die;
int newSession;
int client_skt;
int client_ip;
char *server_address;
int server_skt;
int server_interface_addr;
int client_interface_addr;
int server_ip;
int server_port;
int server_skt_pending_connection;
int state;
int transaction_type;
char *sessionID;
int cur_trk;
int numTracks;
track_info trk[MAX_TRACKS];
char cinbuf[RTSP_SESSION_BUF_SIZE];
int amtInClientInBuffer;
char coutbuf[RTSP_SESSION_BUF_SIZE];
int amtInClientOutBuffer;
char sinbuf[RTSP_SESSION_BUF_SIZE];
int amtInServerInBuffer;
char soutbuf[RTSP_SESSION_BUF_SIZE];
int amtInServerOutBuffer;
int totalContentLength;
int haveParsedServerReplyHeaders;
int contentLength;
char* responseBodyP;
int tempIP;
} rtsp_session;
typedef struct subnet_allow {
struct subnet_allow *next;
int ip;
int range;
} subnet_allow;
typedef struct rtsp_listener {
struct rtsp_listener *next;
int port;
int skt;
} rtsp_listener;
/**********************************************/
int service_listeners();
int service_sessions();
void add_rtsp_port_listener(int address,int port);
void cleanup_listeners(void);
void answer_new_connection(rtsp_listener *listener);
void add_session(rtsp_session *session);
void remove_session(rtsp_session *session);
rtsp_session *new_session(void);
void cleanup_sessions(void);
void cleanup_session(rtsp_session *session);
void service_session(rtsp_session *session);
void service_session_rtp(rtsp_session *session);
void read_config(void);
void add_allow_subnet(int ip, int range);
bool allow_ip(int ip);
void send_rtsp_error(int skt, int refusal);
#endif // __PROXY_H__

View file

@ -0,0 +1,166 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* proxy_plat.h
*
*
*/
#ifndef _PLAT_H_
#define _PLAT_H_
/**********************************************/
#define bool char
#if !defined(mac)
#define true 1
#define false 0
#endif
#if !defined(WIN32)
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif
/**********************************************/
#if defined(WIN32)
#define EACCES WSAEACCES
#define EINTR WSAEINTR
#define EAGAIN WSAEWOULDBLOCK /* good enough? */
#define EPIPE WSAESHUTDOWN /* good enough? */
#define ENOTCONN WSAENOTCONN
#define ECONNRESET WSAECONNRESET
#define EISCONN WSAEISCONN
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#include "WINSOCK.H"
#elif defined(mac)
#define EACCES kEACCESErr
#define EPIPE kEPIPEErr
#define EINTR kEINTRErr
#define EAGAIN kEAGAINErr
#define ENOTCONN kENOTCONNErr
#define ECONNRESET kECONNRESETErr
#define EISCONN kEISCONNErr
#define EINPROGRESS kEINPROGRESSErr
#define EALREADY kEALREADYErr
#endif
/**********************************************/
#define MSEC_PER_SEC 1000
#define USEC_PER_SEC 1000000
#define USEC_PER_MSEC 1000
#define timer_sub(ntime,subtime,eqtime) \
if ((subtime).tv_usec > (ntime).tv_usec) { \
(eqtime).tv_sec = ((ntime).tv_sec - 1) - (subtime).tv_sec; \
(eqtime).tv_usec = (ntime).tv_usec + USEC_PER_SEC - \
(subtime).tv_usec; \
} \
else { \
(eqtime).tv_sec = (ntime).tv_sec - (subtime).tv_sec; \
(eqtime).tv_usec = (ntime).tv_usec - (subtime).tv_usec; \
}
extern char *gConfigFilePath;
extern char *gOptionsString;
extern char gOptionsChar;
typedef struct stats_chunk {
unsigned long elapsedSeconds;
unsigned long bpsReceived;
unsigned long bpsSent;
unsigned long ppsReceived;
unsigned long ppsSent;
unsigned long totalPacketsReceived;
unsigned long totalPacketsSent;
unsigned long numClients;
unsigned long numPorts;
float percentLostPackets;
} stats_chunk;
void daemonize(void);
int init_network(void);
int term_network(void);
int init_ui(void);
int service_ui(int sleep_ticks);
void sleep_milliseconds(int ms);
time_t microseconds();
#define kPENDING_ADDRESS -2
int name_to_ip_num(char *name, int *ip_num, int async);
int get_remote_address(int skt, int *port);
int get_local_address(int skt, int *port);
int get_local_ip_address(void);
bool isReadable(int fd);
bool isWritable(int fd);
int new_socket_udp(void);
int new_socket_tcp(int is_listener);
void close_socket(int skt);
void set_socket_reuse_address(int skt);
void set_socket_max_buf(int skt);
void make_socket_nonblocking(int skt);
int bind_socket_to_address(int skt, int address, int port, int is_listener);
int listen_to_socket(int skt);
int call_is_waiting(int skt, int *incoming_skt);
int accept_connection(int from, int *to);
int get_interface_addr(int skt);
#if DO_ASYNC
pascal void conn_finished_proc(void* contextPtr, OTEventCode code, OTResult /*result*/, void* /*cookie*/);
int connect_to_address(void *context, OTNotifyProcPtr proc, int skt, int address, int port);
#else
int connect_to_address(int skt, int address, int port);
#endif
int tcp_data_ready(int skt);
int recv_udp(int skt, char *buf, int amt, int *fromAddress, int *fromPort);
int send_udp(int skt, char *buf, int amt, int address, int port);
int recv_tcp(int skt, char *buf, int amt);
int send_tcp(int skt, char *buf, int amt);
// int make_udp_port_pair(int *socket1, int *socket2);
int GetLastSocketError(int skt);
void DoStats(stats_chunk *stats);
#if defined(mac) || defined(WIN32)
extern char gLastErrorString[256];
#define ErrorString(a) sprintf(gLastErrorString, a)
#define ErrorString1(a,b) sprintf(gLastErrorString, a, b)
#define ErrorStringS(a,b) sprintf(gLastErrorString, a, b)
#define DebugString(a) printf(a "\n")
#define DebugString1(a,b) printf(a "\n", b)
#define DebugStringS(a,b) printf(a "\n", b)
#else
void ErrorString(char *string);
void ErrorString1(char *string, int d);
void ErrorStringS(char *string, char *arg);
#define DebugString(a) printf(a "\n")
#define DebugString1(a,b) printf(a "\n", b)
#define DebugStringS(a,b) printf(a "\n", b)
#endif
#endif // _PLAT_H_

View file

@ -0,0 +1,579 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
proxy_unix.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/resource.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "util.h"
#include "proxy_plat.h"
#if USE_THREAD
#include "pthread.h"
#endif
#include "../defaultPaths.h"
char *gConfigFilePath = DEFAULTPATHS_ETC_DIR "streamingproxy.conf";
char *gOptionsString = "-c:-p:-d-D-v-h-s-x-i:";
char gOptionsChar = '-';
extern int gMaxPorts;
extern float gDropPercent;
/**********************************************/
int init_network()
{
return 0;
}
/**********************************************/
#define kKILL_THREAD -3
int term_network()
{
int send = kKILL_THREAD;
name_to_ip_num("", &send, true);
return 0;
}
/**********************************************/
typedef struct ghpb_rec {
char name[256];
int *result;
} ghpb_rec, *ghpb;
#if USE_THREAD
void *gethostthread(void *param)
{
struct hostent *hent;
ghpb pb = (ghpb)param;
int id;
pthread_t tid;
int tryCount = 0;
if (*pb->result == kKILL_THREAD)
exit(0);
tid = pthread_self();
again:
hent = gethostbyname(pb->name);
if (hent == NULL) do
{
tryCount ++;
if (h_errno == TRY_AGAIN)
{ if (tryCount < 10)
goto again;
else
return 0;
}
*pb->result = -1;
pthread_exit(NULL);
} while(0);
id = ntohl(((struct in_addr *)(hent->h_addr_list[0]))->s_addr);
*pb->result = id;
free(pb);
pthread_exit(NULL);
return NULL;
}
#endif
/**********************************************/
int name_to_ip_num(char *name, int *ip, int async)
{
int ret;
struct in_addr addr;
int tryAgain = 0;
#if USE_THREAD
ghpb pb = NULL;
pthread_t tid;
#endif
struct hostent *hent;
if (check_IP_cache(name, &ret) != -1)
{
*ip = ret;
return 0;
}
#if USE_THREAD
if (async)
{
*ip = kPENDING_ADDRESS;
pb = (ghpb)malloc(sizeof(ghpb_rec));
strcpy(pb->name, name);
pb->result = ip;
pthread_create(&tid, NULL, gethostthread, (void*)pb);
pthread_detach(tid);
return 1;
}
#endif
again:
tryAgain ++;
if ( inet_aton( name, &addr ) )
{ *ip = ntohl( addr.s_addr );
add_to_IP_cache(name, *ip );
return 0;
}
hent = gethostbyname(name);
if (hent == NULL) {
if (h_errno == TRY_AGAIN)
if (tryAgain < 10)
goto again;
add_to_IP_cache(name, -1);
return -1;
}
*ip = ntohl(((struct in_addr *) (hent->h_addr_list[0]))->s_addr);
add_to_IP_cache(name, *ip);
return 0;
}
/**********************************************/
int get_remote_address(int skt, int *port)
{
#if !defined(sparc) && !defined(SGI) && !defined(WIN32)
unsigned
#endif
int nAddrSize = sizeof(struct sockaddr_in);
struct sockaddr_in remAddr;
int status;
remAddr.sin_addr.s_addr = INADDR_ANY;
status = getpeername(skt, (struct sockaddr*)&remAddr, &nAddrSize);
if (status >= 0)
{
if (port)
*port = ntohs(remAddr.sin_port);
return ntohl(remAddr.sin_addr.s_addr);
}
return -1;
}
/**********************************************/
int get_local_address(int skt, int *port) {
#if !defined(sparc) && !defined(SGI) && !defined(WIN32)
unsigned
#endif
int nAddrSize = sizeof(struct sockaddr_in);
struct sockaddr_in remAddr;
int status;
remAddr.sin_addr.s_addr = INADDR_ANY;
status = getsockname(skt, (struct sockaddr*)&remAddr, &nAddrSize);
if (status >= 0)
{
if (port)
*port = ntohs(remAddr.sin_port);
return ntohl(remAddr.sin_addr.s_addr);
}
return -1;
}
/**********************************************/
static int __local_ip_address = -1;
int get_local_ip_address()
{
char buf[256];
struct hostent *hent;
int tryCount = 0;
if (__local_ip_address != -1)
return __local_ip_address;
if (gethostname(buf, 256) < 0)
return -1;
again:
tryCount ++;
hent = gethostbyname(buf);
if (hent == NULL)
{ if (h_errno == TRY_AGAIN)
{ if (tryCount < 10)
{
goto again;
}
else
{
return 0;
}
}
return -1;
}
__local_ip_address = ntohl(((struct in_addr *)hent->h_addr)->s_addr);
return __local_ip_address;
}
/**********************************************/
void make_socket_nonblocking(int socket)
{
int flag;
flag = fcntl(socket, F_GETFL, 0);
fcntl(socket, F_SETFL, flag | O_NONBLOCK);
}
/**********************************************/
void sleep_milliseconds(int ms)
{
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms - (tv.tv_sec * 1000) ) * 1000;
select(0, NULL, NULL, NULL, &tv);
}
/**********************************************/
time_t microseconds()
{
static bool us_initted = false;
static struct timeval us_time_zero;
struct timeval tv, t;
struct timezone tz;
gettimeofday(&tv, &tz);
if (us_initted == false)
{
us_initted = true;
us_time_zero = tv;
return 0;
}
else
{
timer_sub(tv, us_time_zero, t);
return (t.tv_sec * USEC_PER_SEC + t.tv_usec);
}
}
/**********************************************/
bool isReadable(int fd)
{
/* causes crash fd_set is wrong size if num users > 255
// not needed anyway
fd_set set;
struct timeval tv;
int err;
if (fd == INVALID_SOCKET)
return false;
tv.tv_sec = 0; tv.tv_usec = 0;
FD_ZERO(&set);
FD_SET(fd, &set);
err = select(fd+1, &set, NULL, NULL, &tv);
if (err > 0)
if (FD_ISSET(fd, &set))
return true;
return false;
*/
return true;
}
/**********************************************/
bool isWritable(int fd)
{
/* causes crash fd_set is wrong size if num users > 255
// not needed anyway
fd_set set;
struct timeval tv;
int err;
if (fd == INVALID_SOCKET)
return false;
tv.tv_sec = 0; tv.tv_usec = 0;
FD_ZERO(&set);
FD_SET(fd, &set);
err = select(fd+1, NULL, &set, NULL, &tv);
if (err > 0)
if (FD_ISSET(fd, &set))
return true;
return false;
*/
return true;
}
/**********************************************/
int new_socket_udp(void)
{
int ret;
ret = socket(PF_INET, SOCK_DGRAM, 0);
gMaxPorts++;
set_socket_max_buf(ret);
return ret;
}
/**********************************************/
int new_socket_tcp(int is_listener)
{
int ret;
ret = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
gMaxPorts++;
return ret;
}
/**********************************************/
void set_socket_reuse_address(int skt)
{
int i = 1;
setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i));
}
/**********************************************/
void set_socket_max_buf(int skt)
{
int i = 1;
unsigned int len;
len = sizeof(i);
getsockopt(skt, SOL_SOCKET, SO_SNDBUF, (char*)&i, &len);
/*fprintf(stderr, "sndbuf for socket %d was %d\n", skt, i);*/
i *= 2;
setsockopt(skt, SOL_SOCKET, SO_SNDBUF, (char*)&i, len);
getsockopt(skt, SOL_SOCKET, SO_SNDBUF, (char*)&i, &len);
/*fprintf(stderr, "sndbuf for socket %d is now %d\n", skt, i);*/
getsockopt(skt, SOL_SOCKET, SO_RCVBUF, (char*)&i, &len);
/*fprintf(stderr, "rcvbuf for socket %d was %d\n", skt, i);*/
i *= 2;
setsockopt(skt, SOL_SOCKET, SO_RCVBUF, (char*)&i, len);
getsockopt(skt, SOL_SOCKET, SO_RCVBUF, (char*)&i, &len);
/*fprintf(stderr, "rcvbuf for socket %d is now %d\n", skt, i);*/
}
/**********************************************/
int bind_socket_to_address(int skt, int address, int port, int is_listener)
{
struct sockaddr_in sin;
if (address == -1)
address = INADDR_ANY;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(address);
return bind(skt, (struct sockaddr*)&sin, sizeof(sin));
}
/**********************************************/
void close_socket(int skt)
{
if (skt != INVALID_SOCKET)
{
gMaxPorts--;
close(skt);
}
}
/**********************************************/
int listen_to_socket(int skt)
{
return listen(skt, 5);
}
/**********************************************/
int call_is_waiting(int skt, int *incoming_skt)
{
int ret;
ret = isReadable(skt);
if (ret)
{
*incoming_skt = accept(skt, 0, 0);
if (*incoming_skt <= 0)
{
ret = 0;
}
else
gMaxPorts++;
}
return ret;
}
/**********************************************/
int accept_connection(int from, int *to)
{
// return accept(from, 0, 0);
return *to;
}
/**********************************************/
int connect_to_address(int skt, int address, int port)
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(address);;
return connect(skt, (struct sockaddr*)&sin, sizeof(sin));
}
int get_interface_addr(int skt)
{
int err = 0;
struct sockaddr_in localAddr;
unsigned int len = sizeof(localAddr);
memset(&localAddr, 0, sizeof(localAddr));
err = getsockname(skt, (struct sockaddr*)&localAddr, &len);
return ntohl(localAddr.sin_addr.s_addr);
}
/**********************************************/
int recv_udp(int socket, char *buf, int amt, int *fromip, int *fromport)
{
struct sockaddr_in sin;
int ret;
unsigned int len;
len = sizeof(sin);
memset(&sin, 0, sizeof(sin));
ret = recvfrom(socket, buf, (size_t) amt, 0, (struct sockaddr*)&sin, &len);
if (ret != -1) {
if (fromip)
*fromip = ntohl(sin.sin_addr.s_addr);
if (fromport)
*fromport = ntohs(sin.sin_port);
}
return ret;
}
/**********************************************/
int send_udp(int skt, char *buf, int amt, int address, int port)
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(address);
return sendto(skt, buf, (size_t) amt, 0, (struct sockaddr*)&sin, sizeof(sin));
}
/**********************************************/
int recv_tcp(int socket, char *buf, int amt)
{
return read(socket, buf, (size_t) amt);
}
/**********************************************/
int send_tcp(int socket, char *buf, int amt)
{
return write(socket, buf, (size_t) amt);
}
/**********************************************/
int GetLastSocketError(int skt)
{
return errno;
}
/**********************************************/
int init_ui()
{
return 0;
}
/**********************************************/
int service_ui(int sleep_time)
{
return 0;
}
/**********************************************/
void DoStats(stats_chunk *stats)
{
printf("\033[2J\033[H");
printf("Elapsed Time (seconds) : %lu\n", stats->elapsedSeconds);
printf("Number of clients : %lu\n", stats->numClients);
printf("bps Received : %lu\n", stats->bpsReceived);
printf("bps Sent : %lu\n", stats->bpsSent);
printf("Total Packets Received : %lu\n", stats->totalPacketsReceived);
printf("Total Packets Sent : %lu\n", stats->totalPacketsSent);
printf("pps Received : %lu\n", stats->ppsReceived);
printf("pps Sent : %lu\n", stats->ppsSent);
printf("number of ports used : %lu\n", stats->numPorts);
printf("packet loss percent : %f\n", stats->percentLostPackets);
printf("force drop percent : %f\n",gDropPercent);
}
/**********************************************/
void ErrorString(char *string)
{
fprintf(stderr, string);
}
/**********************************************/
void ErrorString1(char *string, int d)
{
fprintf(stderr, string, d);
}
/**********************************************/
void ErrorStringS(char *string, char *arg)
{
fprintf(stderr, string, arg);
}
void daemonize()
{
switch (fork()) {
case -1: /* error */
fprintf(stderr, "can't daemonize!\n");
case 0: /* child */
break;
default: /* parent */
exit(0);
}
}

View file

@ -0,0 +1,474 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: shared_udp.c
Contains: UDP Sockets implementation with shared ports
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#if defined(unix)
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/resource.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/socket.h>
#elif defined(win32)
#include "WINSOCK.H"
#include "regex.h"
#elif defined(mac)
#include <MacTypes.h>
#include "OpenTransport.h"
#endif
#include "shared_udp.h"
#include "proxy_plat.h"
#if DEBUG
#define DEBUGPRINT(x) printf x
#else
#define DEBUGPRINT(x)
#endif
/**********************************************/
shok *gShokList = NULL;
/**********************************************/
ipList *find_ip_in_list(ipList *list, int ip)
{
ipList *cur = list;
DEBUGPRINT(( "-- -- looking for IP %x in IP list\n", ip));
while (cur) {
DEBUGPRINT(("-- -- vs. %x\n", cur->ip));
if (cur->ip == ip) {
DEBUGPRINT(("-- -- FOUND\n"));
return cur;
}
cur = cur->next;
}
DEBUGPRINT(("-- -- NOT FOUND\n"));
return NULL;
}
/**********************************************/
int add_ip_to_list(ipList **list, int ip)
{
ipList *newEl;
newEl = (ipList*)malloc(sizeof(ipList));
if (!newEl)
return false;
newEl->ip = ip;
newEl->what_to_do = NULL;
newEl->what_to_do_it_with = NULL;
newEl->next = *list;
*list = newEl;
return true;
}
/**********************************************/
int remove_ip_from_list(ipList **list, int ip)
{
ipList *last, *theEl = *list;
if (theEl->ip == ip) {
*list = theEl->next;
free(theEl);
return true;
}
last = theEl;
theEl = theEl->next;
while (theEl) {
if (theEl->ip == ip) {
last->next = theEl->next;
free(theEl);
return true;
}
last = theEl;
theEl = theEl->next;
}
return false;
}
/**********************************************/
shok *find_available_shok(int fromIP, int toIP, int withSib)
{
shok *cur = gShokList;
while (cur) {
DEBUGPRINT(("-- looking for IP %x in shok %p\n", toIP, cur));
if (find_ip_in_list(cur->ips, toIP) == NULL) {
if (withSib) {
DEBUGPRINT(("-- looking for IP %x in SIB shok %p\n", toIP, cur->sib));
if (find_ip_in_list(cur->sib->ips, toIP) == NULL)
return cur;
}
else
return cur;
}
cur = cur->next;
}
return NULL;
}
/**********************************************/
int add_ips_to_shok(shok *theShok, int fromIP, int toIP, int withSib)
{
add_ip_to_list(&(theShok->ips), toIP);
if (withSib)
add_ip_to_list(&(theShok->sib->ips), toIP);
return 1;
}
/**********************************************/
static int gUDPPortMin = 4000;
static int gUDPPortMax = 65536;
#define sInvalidPort -1
static int gNextPort = sInvalidPort;
void set_udp_port_min_and_max(int min, int max)
{
gUDPPortMin = min;
gUDPPortMax = max;
if (gUDPPortMin & 0x1)
gUDPPortMin++;
}
/**********************************************/
int remove_shok(shok *theShok, int withSib)
{
shok *cur = NULL, *last;
cur = gShokList;
if (cur == theShok) {
gShokList = cur->next;
goto doSib;
}
last = cur;
cur = cur->next;
while (cur) {
if (cur == theShok) {
last->next = cur->next;
goto doSib;
}
last = cur;
cur = cur->next;
}
return false;
doSib:
if (cur->sib)
cur->sib->sib = NULL;
if (withSib && cur->sib)
remove_shok(cur->sib, false);
{
ipList *ipn, *ipl = cur->ips;
while (ipl) {
ipn = ipl->next;
free(ipn);
ipl = ipn;
}
}
close_socket(cur->socket);
free(cur);
return true;
}
/**********************************************/
void remove_shok_ref(shok *theShok, int fromIP, int toIP, int withSib)
{
remove_ip_from_list(&(theShok->ips), toIP);
if (withSib)
remove_ip_from_list(&(theShok->sib->ips), toIP);
if (theShok->sib->ips == NULL)
remove_shok(theShok->sib, false);
if (theShok->ips == NULL)
remove_shok(theShok, false);
}
/**********************************************/
shok *make_new_shok(int fromIP, int toIP, int withSib)
{
shok *theShok1 = NULL, *theShok2 = NULL;
int skt1 = INVALID_SOCKET, skt2 = INVALID_SOCKET;
int port1 = sInvalidPort;
int port2 = sInvalidPort;
theShok1 = (shok*)malloc(sizeof(shok));
if (!theShok1)
goto bail_error;
if (withSib) {
theShok2 = (shok*)malloc(sizeof(shok));
if (!theShok2)
goto bail_error;
}
if (gNextPort == -1)
gNextPort = gUDPPortMin;
retry:
if ((skt1 = new_socket_udp()) == SOCKET_ERROR)
goto bail_error;
if (skt1 == 0) {
if (GetLastSocketError(skt1) == EINPROGRESS || GetLastSocketError(skt1) == EAGAIN)
goto retry;
else
goto bail_error;
}
do {
if ((gNextPort & 0x1) && withSib)
gNextPort++;
if (gNextPort > gUDPPortMax)
gNextPort = gUDPPortMin;
} while (bind_socket_to_address(skt1, fromIP, port1 = gNextPort++, false) != 0);
if (withSib) {
retry_rtcp:
if ((skt2 = new_socket_udp()) == SOCKET_ERROR)
goto bail_error;
if (skt2 == 0) {
if (GetLastSocketError(skt2) == EINPROGRESS || GetLastSocketError(skt2) == EAGAIN)
goto retry_rtcp;
else
goto bail_error;
}
if (bind_socket_to_address(skt2, fromIP, port2 = gNextPort++, false) != 0) {
close_socket(skt1);
close_socket(skt2);
skt1 = INVALID_SOCKET;
skt2 = INVALID_SOCKET;
goto retry;
}
}
make_socket_nonblocking(skt1);
theShok1->socket = skt1;
theShok1->port = port1;
theShok1->ips = NULL;
if (withSib) {
make_socket_nonblocking(skt2);
theShok2->socket = skt2;
theShok2->port = port2;
theShok2->ips = NULL;
theShok2->sib = theShok1;
theShok1->sib = theShok2;
theShok1->next = theShok2;
theShok2->next = gShokList;
}
else {
theShok1->sib = NULL;
theShok1->next = gShokList;
}
add_ips_to_shok(theShok1, fromIP, toIP, withSib);
gShokList = theShok1;
return theShok1;
bail_error:
printf("make_new_shok bail_error\n");
close_socket(skt1);
close_socket(skt2);
if (theShok1 != NULL)
free(theShok1);
if (theShok2 != NULL)
free(theShok2);
return NULL;
}
/**********************************************/
int make_udp_port_pair(int fromIP, int toIP, shok **rtpSocket, shok **rtcpSocket)
{
shok *theShok;
DEBUGPRINT(("MAKE_UDP_PORT_PAIR from %x to %x\n", fromIP, toIP));
DEBUGPRINT(("looking for available shok\n"));
if ((theShok = find_available_shok(fromIP, toIP, true)) != NULL) {
DEBUGPRINT(("found available shok : SOCKET [%d] PORT [%d]\n", theShok->socket, theShok->port));
add_ips_to_shok(theShok, fromIP, toIP, true);
}
else {
theShok = make_new_shok(fromIP, toIP, true);
DEBUGPRINT(("couldn't find shok - made new one : SOCKET [%d] PORT [%d]\n", theShok->socket, theShok->port));
}
if (theShok && theShok->sib) {
*rtpSocket = theShok;
*rtcpSocket = theShok->sib;
return 1;
}
else
return -1;
}
/**********************************************/
int upon_receipt_from(shok *theShok, int fromIP, do_routine doThis, void *withThis)
{
ipList *listEl;
DEBUGPRINT(( "UPON_RECEIPT_FROM %x do routine %p\n", fromIP, doThis));
listEl = find_ip_in_list(theShok->ips, fromIP);
if (!listEl)
return -1;
listEl->what_to_do = doThis;
listEl->what_to_do_it_with = withThis;
return 0;
}
/**********************************************/
extern int gNeedsService;
extern unsigned long gPacketsReceived;
extern unsigned long gPacketsSent;
extern unsigned long gBytesReceived;
extern unsigned long gBytesSent;
extern float gDropPercent;
extern unsigned long gDropDelta;
/**********************************************/
int service_shoks()
{
shok *cur;
char buf[2048];
cur = gShokList;
while (cur) {
do_routine doit;
int ret, fromPort, fromIP;
again:
doit = NULL;
ret = recv_udp(cur->socket, buf, 2048, &fromIP, &fromPort);
if (ret > 0) {
ipList *ipl = NULL;
DEBUGPRINT(("Got %d bytes for %x on port %d on socket %d\n", ret, fromIP, fromPort, cur->socket));
gBytesReceived += ret;
gPacketsReceived++;
ipl = find_ip_in_list(cur->ips, fromIP);
if (ipl)
doit = ipl->what_to_do;
if (doit && ipl) {
gNeedsService++;
ret = (*doit)(ipl->what_to_do_it_with, buf, ret);
if (ret == -1) {
// what to do about termination, etc.
DEBUGPRINT(("put returns error %d\n", errno));
}
else if (ret == 0) {
// client/server whatever died
if (((trans_pb*)ipl->what_to_do_it_with)->status)
*(((trans_pb*)ipl->what_to_do_it_with)->status) = 1;
DEBUGPRINT(("client/server died\n"));
}
// what to do about incomplete packet transmission
}
goto again;
}
else if (ret < 0) {
if (errno != 11)
DEBUGPRINT(("recv_udp returns errno %d\n", errno));
// what to do about termination, etc.
}
cur = cur->next;
}
return 0;
}
/**********************************************/
int transfer_data(void *refCon, char *buf, int bufSize)
{
trans_pb *tpb = (trans_pb*)refCon;
int ret;
int isRTCP = 0;
if (!tpb)
return -1;
if (strstr(tpb->socketName,"RTCP"))
{ //printf("shared_udp.c transfer_data %s\n",tpb->socketName);
isRTCP = 1;
}
tpb->packetCount++;
if (gDropPercent > 0.0 )
{ int packetDropped = 0;
//printf("transfer_data tpb->nextDropPacket=%qd tpb->packetCount=%qd\n",tpb->nextDropPacket, tpb->packetCount);
if (tpb->packetCount == tpb->nextDropPacket)
{ tpb->droppedPacketCount ++;
tpb->nextDropPacket = 0;
//printf("transfer_data tpb->droppedPacketCount=%qd tpb->packetCount=%qd\n",tpb->droppedPacketCount, tpb->packetCount);
packetDropped = 1;
}
if (tpb->nextDropPacket == 0)
{
int offset = 0;
if (gDropPercent <= 50.0)
offset = 100.0 / gDropPercent; // drop the percent packet
else if (gDropPercent < 100.0 )
offset = 1 + ( ( (rand() % 49) <= ( gDropPercent - 47.0) ) ? 0 : 1);// drop random 1 to 2 packets 1 == next packet or 100% 2== every other 50%
else
offset = 1; // 100% = drop next packet
tpb->nextDropPacket = tpb->packetCount + offset;
}
if (packetDropped)
return bufSize;
}
ret = send_udp(tpb->send_from->socket, buf, bufSize, tpb->send_to_ip, tpb->send_to_port);
DEBUGPRINT(("Sent %d bytes to %x on port %d on socket %d\n",
ret, tpb->send_to_ip, tpb->send_to_port, tpb->send_from->socket));
if (ret > 0)
{ gBytesSent += ret;
gPacketsSent++;
}
return ret;
}

View file

@ -0,0 +1,84 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: shared_udp.h
Contains: udp sockets implementation with shared ports
*/
#ifndef __SHARED_UDP_H__
#define __SHARED_UDP_H__
#define MAX_SOCKET_NAME 32
/**********************************************/
typedef int (*do_routine)(void * refCon, char *buf, int bufSize);
typedef struct ipList {
struct ipList *next;
int ip;
do_routine what_to_do;
void *what_to_do_it_with;
} ipList;
typedef struct shok {
struct shok *next;
int socket;
int port;
ipList *ips;
struct shok *sib; // sibling - rtcp or rtp
} shok;
typedef struct trans_pb {
int *status; // set to 1 when needs to die
shok *send_from;
int send_to_ip;
int send_to_port;
long long int packetSendCount;
long long int nextDropPacket;
long long int droppedPacketCount;
long long int packetCount;
char socketName[MAX_SOCKET_NAME];
} trans_pb;
/**********************************************/
ipList *find_ip_in_list(ipList *list, int ip);
int add_ip_to_list(ipList **list, int ip);
int remove_ip_from_list(ipList **list, int ip);
shok *find_available_shok(int fromIP, int toIP, int withSib);
int add_ips_to_shok(shok *theShok, int fromIP, int toIP, int withSib);
void set_udp_port_min_and_max(int min, int max);
int remove_shok(shok *theShok, int withSib);
void remove_shok_ref(shok *theShok, int fromIP, int toIP, int withSib);
shok *make_new_shok(int fromIP, int toIP, int withSib);
int make_udp_port_pair(int fromIP, int toIP, shok **rtpSocket, shok **rtcpSocket);
int upon_receipt_from(shok *theShok, int fromIP, do_routine doThis, void *withThis);
int service_shoks();
int transfer_data(void *refCon, char *buf, int bufSize);
#endif // __SHARED_UDP_H__

273
StreamingProxy.tproj/util.c Normal file
View file

@ -0,0 +1,273 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* util.c
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <assert.h>
#include "util.h"
static char to_lower(int c);
/**********************************************/
static char ip_string_buffer[20];
char *ip_to_string(int ip) {
sprintf(ip_string_buffer, "%d.%d.%d.%d",
(ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16,
(ip & 0x0000ff00) >> 8, (ip & 0x000000ff));
return ip_string_buffer;
}
/**********************************************/
static char to_lower(int c)
{
if (c >= 'A' && c <= 'Z')
return ((c - 'A') + 'a');
return c;
}
/**********************************************/
char *str_dup(char *str)
{
char *ret;
ret = (char*)malloc(strlen(str)+1);
strcpy(ret, str);
return ret;
}
/**********************************************/
int str_casecmp(char *str1, char *str2)
{
int ret;
ret = *str1 - *str2;
while (*str1 && *str2 && ((ret = *str1++ - *str2++) == 0))
;
return ret;
}
/**********************************************/
int strn_casecmp(char *str1, char *str2, int l)
{
int ret;
ret = to_lower( (char) *str1) - to_lower((char) *str2);
while (l-- && to_lower(*str1) && to_lower(*str2) && ((ret = to_lower(*str1++) - to_lower(*str2++)) == 0))
;
return ret;
}
/*
grab a full line from input
put into strBuff as 0 terminated
must maintain the exact eol that the
input string has.
return next position.
*/
char* get_line_str( char* strBuff, char *input, int buffSize)
{
char *p = input;
int sawEOLChar = 0;
assert( strBuff != NULL && input != NULL && buffSize > 0);
memset(strBuff, 0, (size_t) buffSize);
while( *p )
{
assert( buffSize > 0 );
if ( *p == '\r' || *p == '\n' )
{ // grab all eol chars
sawEOLChar = 1;
*strBuff = *p;
strBuff++;
buffSize--;
}
else if ( sawEOLChar )
{
// we saw eol char(s) and now this is not one
// that means we're done
break;
}
else
{
// grab all line chars
*strBuff = *p;
strBuff++;
buffSize--;
}
p++;
}
*strBuff = 0;
// we're not going to change the contents
// of input, but the caller may have the right too.
return (char*)p;
}
/**********************************************
subdivide a string along the delimeter
points in delim
return the next start point in stringp
return the current string start;
*/
char *str_sep(char **stringp, char *delim)
{
int j, dl, i, sl;
char *newstring, *ret;
if (*stringp == NULL)
return NULL;
dl = strlen(delim);
sl = strlen(*stringp);
newstring = NULL;
ret = *stringp;
for (i=0; i<sl; i++)
{
for (j=0; j<dl; j++)
{
if ((*stringp)[i] == delim[j])
{
(*stringp)[i] = '\0';
newstring = &((*stringp)[i+1]);
i = sl; j = dl;
}
}
}
*stringp = newstring;
return ret;
}
/**********************************************/
typedef struct t_ip_cache {
struct t_ip_cache *next;
char *name;
int ip;
} t_ip_cache;
static t_ip_cache *gIPcache = NULL;
int check_IP_cache(char *name, int *ip)
{
t_ip_cache *cur = gIPcache;
while (cur) {
if (str_casecmp(name, cur->name) == 0) {
*ip = cur->ip;
return 0;
}
cur = cur->next;
}
return -1;
}
/**********************************************/
int add_to_IP_cache(char *name, int ip)
{
t_ip_cache *cur;
cur = (t_ip_cache*)malloc(sizeof(t_ip_cache));
if (cur == NULL)
return -1;
cur->ip = ip;
cur->name = malloc(strlen(name) + 1);
strcpy(cur->name, name);
cur->next = gIPcache;
gIPcache = cur;
return 0;
}
/**********************************************/
int inet_aton_(char *s, int *retval)
{
int i, l, x, el[4], ret, good = 1;
x = 0, ret = 0;
l = strlen(s);
el[0] = 0;
for (i=0; i<l; i++) {
if (s[i] == '.') {
x++;
if (x > 3) {
good = 0;
break;
}
el[x] = 0;
}
else if (s[i] >= '0' && s[i] <= '9') {
el[x] *= 10;
el[x] += s[i] - '0';
}
else
good = 0;
}
switch (x) {
case 3:
ret = ( ((el[0] << 24) & 0xff000000) |
((el[1] << 16) & 0x00ff0000) |
((el[2] << 8 ) & 0x0000ff00) |
(el[3] & 0x000000ff) );
break;
case 2:
ret = ( ((el[0] << 24) & 0xff000000) |
((el[1] << 16) & 0x00ff0000) |
(el[2] & 0x0000ffff) );
break;
case 1:
ret = (((el[0] << 24) & 0xff000000) |
(el[1] & 0x00ffffff) );
break;
case 0:
ret = el[0];
break;
}
*retval = ret;
return good;
}

View file

@ -0,0 +1,42 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
* util.h
*
*
*/
/**********************************************/
char *ip_to_string(int ip);
int inet_aton_(char *s, int *retval);
char *str_sep(char **stringp, char *delim);
char *str_dup(char *str);
int str_casecmp(char *str1, char *str2);
int strn_casecmp(char *str1, char *str2, int l);
int check_IP_cache(char *name, int *ip);
int add_to_IP_cache(char *name, int ip);
char* get_line_str( char* strBuff, char *input, int buffSize );