186 lines
4.4 KiB
C
186 lines
4.4 KiB
C
#include <phdk.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#ifdef _WIN32
|
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
|
#include <winsock2.h>
|
|
#else
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/tcp.h>
|
|
#include <netdb.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "tcp.h"
|
|
|
|
int growl_tcp_parse_hostname( const char *const server , int default_port , struct sockaddr_in *const sockaddr );
|
|
|
|
void growl_tcp_write_raw( SOCKET sock, const unsigned char * data, const int data_length )
|
|
{
|
|
send(sock, data, data_length, 0);
|
|
}
|
|
|
|
void growl_tcp_write( SOCKET sock , const char *const format , ... )
|
|
{
|
|
int length;
|
|
char *output;
|
|
char *stop;
|
|
|
|
va_list ap;
|
|
|
|
va_start( ap , format );
|
|
length = vsnprintf( NULL , 0 , format , ap );
|
|
va_end(ap);
|
|
|
|
va_start(ap,format);
|
|
output = (char*)PhAllocateSafe(length+1);
|
|
if (!output) {
|
|
va_end(ap);
|
|
return;
|
|
}
|
|
vsnprintf( output , length+1 , format , ap );
|
|
va_end(ap);
|
|
|
|
while ((stop = strstr(output, "\r\n"))) strcpy(stop, stop + 1);
|
|
|
|
send( sock , output , length , 0 );
|
|
send( sock , "\r\n" , 2 , 0 );
|
|
|
|
PhFree(output);
|
|
}
|
|
|
|
char *growl_tcp_read(SOCKET sock) {
|
|
const int growsize = 80;
|
|
char c = 0;
|
|
char* line = (char*) PhAllocateSafe(growsize);
|
|
if (line) {
|
|
int len = growsize, pos = 0;
|
|
char* newline;
|
|
while (line) {
|
|
if (recv(sock, &c, 1, 0) <= 0) break;
|
|
if (c == '\r') continue;
|
|
if (c == '\n') break;
|
|
line[pos++] = c;
|
|
if (pos >= len) {
|
|
len += growsize;
|
|
newline = (char*) realloc(line, len);
|
|
if (!newline) {
|
|
PhFree(line);
|
|
return NULL;
|
|
}
|
|
line = newline;
|
|
}
|
|
}
|
|
line[pos] = 0;
|
|
}
|
|
return line;
|
|
}
|
|
|
|
/* dmex: modified to use INVALID_SOCKET and SOCKET_ERROR */
|
|
SOCKET growl_tcp_open(const char* server) {
|
|
SOCKET sock = INVALID_SOCKET;
|
|
#ifdef _WIN32
|
|
char on;
|
|
#else
|
|
int on;
|
|
#endif
|
|
struct sockaddr_in serv_addr;
|
|
|
|
if( growl_tcp_parse_hostname( server , 23053 , &serv_addr ) == -1 ) {
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
|
|
perror("create socket");
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
|
|
perror("connect");
|
|
closesocket(sock); // dmex: fixed handle leaking on error
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
on = 1;
|
|
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
|
|
perror("setsockopt");
|
|
closesocket(sock); // dmex: fixed handle leaking on error
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
return sock;
|
|
}
|
|
|
|
/* dmex: modified to use INVALID_SOCKET */
|
|
void growl_tcp_close(SOCKET sock) {
|
|
#ifdef _WIN32
|
|
if (sock != INVALID_SOCKET) closesocket(sock);
|
|
#else
|
|
if (sock > 0) close(sock);
|
|
#endif
|
|
}
|
|
|
|
int growl_tcp_parse_hostname( const char *const server , int default_port , struct sockaddr_in *const sockaddr )
|
|
{
|
|
char *hostname = PhDuplicateBytesZSafe((PSTR)server);
|
|
char *port = strchr( hostname, ':' );
|
|
struct hostent* host_ent;
|
|
if( port != NULL )
|
|
{
|
|
*port = '\0';
|
|
port++;
|
|
default_port = atoi(port);
|
|
}
|
|
|
|
host_ent = gethostbyname(hostname);
|
|
if( host_ent == NULL )
|
|
{
|
|
perror("gethostbyname");
|
|
PhFree(hostname);
|
|
return -1;
|
|
}
|
|
|
|
// dmex: fixed wrong sizeof argument
|
|
memset( sockaddr , 0 , sizeof(struct sockaddr_in) );
|
|
sockaddr->sin_family = AF_INET;
|
|
memcpy( &sockaddr->sin_addr , host_ent->h_addr , host_ent->h_length );
|
|
sockaddr->sin_port = htons(default_port);
|
|
|
|
PhFree(hostname);
|
|
return 0;
|
|
}
|
|
|
|
int growl_tcp_datagram( const char *server , const unsigned char *data , const int data_length )
|
|
{
|
|
int result;
|
|
struct sockaddr_in serv_addr;
|
|
SOCKET sock = 0;
|
|
|
|
if( growl_tcp_parse_hostname( server , 9887 , &serv_addr ) == -1 )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
if( sock == INVALID_SOCKET )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if( sendto(sock, (char*)data , data_length , 0 , (struct sockaddr*)&serv_addr , sizeof(serv_addr) ) > 0 )
|
|
{
|
|
result = 0;
|
|
}
|
|
else
|
|
{
|
|
result = 1;
|
|
}
|
|
|
|
closesocket(sock);
|
|
return result;
|
|
}
|