Subversion Repositories svn.mios32

Rev

Rev 1724 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1003 tk 1
/* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
2
// $Id: UdpSocket.cpp 1803 2013-06-15 16:39:45Z tk $
3
/*
4
 * UDP Socket
5
 *
6
 * We don't use the Juce based DatagramSocket since it behaves sometimes strange
7
 * (e.g. hangups) and since it seems that it isn't made for exchanging datagrams
8
 * without blocking.
9
 *
10
 * ==========================================================================
11
 *
12
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
13
 *  Licensed for personal non-commercial use only.
14
 *  All other rights reserved.
15
 *
16
 * ==========================================================================
17
 */
18
 
19
 
20
// Unix headers for socket connections - add option for Windows here
1004 philetaylo 21
#ifdef WIN32
22
  #include <winsock2.h>
23
#else
24
  #include <sys/types.h>
25
  #include <sys/socket.h>
26
  #include <netinet/in.h>
27
  #include <netdb.h>
1803 tk 28
  #include <unistd.h>
1004 philetaylo 29
#endif
30
#include "UdpSocket.h"
1003 tk 31
#include <fcntl.h>
32
 
33
 
34
//==============================================================================
35
UdpSocket::UdpSocket()
36
    : oscServerSocket(-1)
37
{
38
}
39
 
40
UdpSocket::~UdpSocket()
41
{
42
    disconnect();
43
}
44
 
45
 
46
//==============================================================================
1005 tk 47
bool UdpSocket::connect(const String& remoteHost, const unsigned& _portNumberRead, const unsigned& _portNumberWrite)
1003 tk 48
{
49
    struct sockaddr_in hostAddressInfo;
50
    struct hostent *remoteHostInfo;
51
 
52
    if( oscServerSocket != -1 )
53
        return false;
54
 
1005 tk 55
    portNumberWrite = _portNumberWrite;
1003 tk 56
 
1004 philetaylo 57
#ifdef WIN32
58
    WSADATA wsaData;
59
    // Initialize Winsock
60
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) {
61
        return false;
62
    }
63
#endif
64
 
65
 
1003 tk 66
    // make a socket
67
    if( (oscServerSocket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
68
        oscServerSocket = -1;
1004 philetaylo 69
#ifdef WIN32
70
        WSACleanup();
71
#endif
1003 tk 72
        return false;
73
    }
74
 
75
    // get IP address from name
76
#if JUCE_MAJOR_VERSION==1 && JUCE_MINOR_VERSION<51
77
    remoteHostInfo = gethostbyname((const char *)remoteHost);
78
#else
1724 tk 79
    remoteHostInfo = gethostbyname(remoteHost.toUTF8().getAddress());
1003 tk 80
#endif
81
 
1004 philetaylo 82
    // This looks to be required in windows as remoteHostInfo is null if the host is not found
83
    // and that will cause an exception in the memcpy() below
84
    if (remoteHostInfo == NULL) {
1078 tk 85
#ifdef WIN32
1004 philetaylo 86
        WSACleanup();
1078 tk 87
#endif
1004 philetaylo 88
        return false;
89
    }
90
 
91
    // fill address struct
1003 tk 92
    memcpy(&remoteAddress, remoteHostInfo->h_addr, remoteHostInfo->h_length);
93
 
94
    hostAddressInfo.sin_addr.s_addr=INADDR_ANY;
1005 tk 95
    hostAddressInfo.sin_port=htons(_portNumberRead);
1003 tk 96
    hostAddressInfo.sin_family=AF_INET;
97
 
98
    if( bind(oscServerSocket, (struct sockaddr*)&hostAddressInfo, sizeof(hostAddressInfo)) < 0 ) {
99
        disconnect();
1004 philetaylo 100
#ifdef WIN32
101
        WSACleanup();
102
#endif
1003 tk 103
        return false;
104
    }
105
 
106
    // make it non-blocking
1004 philetaylo 107
#ifdef WIN32
108
    u_long iMode = 1;
109
    if (ioctlsocket(oscServerSocket, FIONBIO, &iMode)!=0) {
110
        WSACleanup();
111
        return false; // error setting socket status
112
    }
113
#else
1003 tk 114
    int status;
1078 tk 115
    if( (status=fcntl(oscServerSocket, F_GETFL)) < 0 ) {
1003 tk 116
        disconnect();
117
        return false; // error while getting socket status
118
    }
119
 
120
    status |= O_NONBLOCK;
121
 
122
    if( fcntl(oscServerSocket, F_SETFL, status) < 0 ) {
123
        disconnect();
124
        return false; // error while setting socket status
125
    }
1004 philetaylo 126
#endif
1003 tk 127
 
128
    return true;
129
}
130
 
131
//==============================================================================
132
void UdpSocket::disconnect(void)
133
{
1004 philetaylo 134
#ifdef WIN32
135
    closesocket(oscServerSocket);
136
    WSACleanup();
137
#else
1003 tk 138
    close(oscServerSocket);
1004 philetaylo 139
#endif
1003 tk 140
    oscServerSocket = -1;
141
}
142
 
143
//==============================================================================
144
unsigned UdpSocket::write(unsigned char *datagram, unsigned len)
145
{
146
    if( oscServerSocket < 0 )
147
        return 0;
148
 
149
    struct sockaddr_in remoteAddressInfo;
150
    remoteAddressInfo.sin_addr.s_addr = remoteAddress;
1005 tk 151
    remoteAddressInfo.sin_port        = htons(portNumberWrite);
1003 tk 152
    remoteAddressInfo.sin_family      = AF_INET;
153
 
154
    const struct sockaddr* remoteAddressInfoPtr = (sockaddr *)&remoteAddressInfo; // the sendto function expects a sockaddr parameter...
1004 philetaylo 155
    return sendto(oscServerSocket, (const char*)datagram, len, 0, remoteAddressInfoPtr, sizeof(remoteAddressInfo));
1003 tk 156
}
157
 
158
 
159
//==============================================================================
160
unsigned UdpSocket::read(unsigned char *datagram, unsigned maxLen)
161
{
162
    if( oscServerSocket < 0 )
163
        return 0;
164
 
1004 philetaylo 165
    int len = recv(oscServerSocket,(char*) datagram, maxLen, 0);
1003 tk 166
 
167
    return (len < 0) ? 0 : len;
168
}