diff -r -u libmms-0.6-old/configure.in libmms-0.6-new/configure.in --- libmms-0.6-old/configure.in 2010-05-31 10:13:44 +0000 +++ libmms-0.6-new/configure.in 2010-09-20 13:03:22 +0000 @@ -4,12 +4,25 @@ AC_CONFIG_SRCDIR(configure.in) AC_ISC_POSIX +AC_CANONICAL_HOST AC_PROG_CC AC_STDC_HEADERS +AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL AC_PROG_LIBTOOL AC_PROG_INSTALL +dnl Checks for header files. +AC_CHECK_HEADERS([sys/socket.h netinet/in.h netdb.h windows.h winsock2.h]) + +case $host in + *beos*) + AC_DEFINE([BEOS],1,[Define if compiling on BeOS system.]) + ;; + *mingw*) + MMS_LIBS="$MMS_LIBS -lws2_32" + ;; +esac PKG_CHECK_MODULES(GLIB, glib-2.0) AC_SUBST(GLIB_CFLAGS) diff -r -u libmms-0.6-old/src/bswap.h libmms-0.6-new/src/bswap.h --- libmms-0.6-old/src/bswap.h 2010-05-30 11:28:26 +0000 +++ libmms-0.6-new/src/bswap.h 2010-09-20 13:04:44 +0000 @@ -32,6 +32,21 @@ * Oh, and one more thing -- they take *pointers*, not actual ints */ +#if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__) + +/* Actually these platforms do not support u_int*_t types */ +#include + +#define LE_16(val) (GINT16_FROM_LE (*((uint16_t*)(val)))) +#define BE_16(val) (GINT16_FROM_BE (*((uint16_t*)(val)))) +#define LE_32(val) (GINT32_FROM_LE (*((uint32_t*)(val)))) +#define BE_32(val) (GINT32_FROM_BE (*((uint32_t*)(val)))) + +#define LE_64(val) (GINT64_FROM_LE (*((uint64_t*)(val)))) +#define BE_64(val) (GINT64_FROM_BE (*((uint64_t*)(val)))) + +#else + #define LE_16(val) (GINT16_FROM_LE (*((u_int16_t*)(val)))) #define BE_16(val) (GINT16_FROM_BE (*((u_int16_t*)(val)))) #define LE_32(val) (GINT32_FROM_LE (*((u_int32_t*)(val)))) @@ -40,4 +55,6 @@ #define LE_64(val) (GINT64_FROM_LE (*((u_int64_t*)(val)))) #define BE_64(val) (GINT64_FROM_BE (*((u_int64_t*)(val)))) +#endif + #endif /* BSWAP_H_INCLUDED */ diff -r -u libmms-0.6-old/src/mms.c libmms-0.6-new/src/mms.c --- libmms-0.6-old/src/mms.c 2010-05-31 10:13:04 +0000 +++ libmms-0.6-new/src/mms.c 2010-09-20 13:03:42 +0000 @@ -28,11 +28,21 @@ #include "config.h" #endif +#ifdef HAVE_WINSOCK2_H +#include +#endif + #include #include +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_NETDB_H #include +#endif #include #include #include @@ -53,6 +63,20 @@ #include "uri.h" #include "mms-common.h" +#ifdef _WIN32 +#define set_errno(_err) WSASetLastError(_err) +#define get_errno() WSAGetLastError() +#define is_errno(_err) (WSAGetLastError() == (_err)) +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#else +#define set_errno(_err) errno = (_err) +#define get_errno() errno +#define is_errno(_err) (errno == (_err)) +#define closesocket(_s) close(_s) +#endif + /* * mms specific types */ @@ -158,16 +182,20 @@ { off_t len = 0, ret; /* lprintf("%d\n", fallback_io_select(data, socket, MMS_IO_READ_READY, 1000)); */ - errno = 0; + set_errno(0); while (len < num) { +#ifdef WIN32 + ret = (off_t)recv(socket, buf + len, num - len, 0); +#else ret = (off_t)read(socket, buf + len, num - len); +#endif if(ret == 0) break; /* EOF */ if(ret < 0) { lprintf("mms: read error @ len = %lld: %s\n", (long long int) len, - strerror(errno)); - switch(errno) + strerror(get_errno())); + switch(get_errno()) { case EAGAIN: continue; @@ -183,7 +211,11 @@ static off_t fallback_io_write(void *data, int socket, char *buf, off_t num) { +#ifdef WIN32 + return (off_t)send(socket, buf, num, 0); +#else return (off_t)write(socket, buf, num); +#endif } static int fallback_io_tcp_connect(void *data, const char *host, int port) @@ -191,6 +223,11 @@ struct hostent *h; int i, s; +#ifdef BEOS + int on_state = 1; +#elif defined HAVE_WINSOCK2_H + unsigned long arg = 1; +#endif h = gethostbyname(host); if (h == NULL) { @@ -200,14 +237,25 @@ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == -1) { - lprintf("mms: failed to create socket: %s\n", strerror(errno)); + lprintf("mms: failed to create socket: %s\n", strerror(get_errno())); return -1; } +/* set socket to non-blocking */ +#ifdef BEOS + if (setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(on)) == -1) { + return -1; + } +#elif defined WIN32 + if (ioctlsocket(s, FIONBIO, &arg)) { + return -1; + } +#else if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) & ~O_NONBLOCK) == -1) { - lprintf("mms: failed to set socket flags: %s\n", strerror(errno)); + lprintf("mms: failed to set socket flags: %s\n", strerror(get_errno())); return -1; } +#endif for (i = 0; h->h_addr_list[i]; i++) { struct in_addr ia; @@ -218,16 +266,43 @@ sin.sin_addr = ia; sin.sin_port = htons(port); - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==-1 && errno != EINPROGRESS) { + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==-1 && is_errno(EINPROGRESS)) { continue; } return s; } - close(s); + closesocket(s); return -1; } +#ifdef _WIN32 +static int iWinsockNeed = WSASYSNOTREADY; + +static int mms_internal_winsock_load(void) +{ + if (iWinsockNeed) { + WORD wVersionReq = MAKEWORD(1, 1); + WSADATA wsaData; + + iWinsockNeed = WSAStartup(wVersionReq, &wsaData); + if (iWinsockNeed != 0) { + /* Cannot load Winsock DLL. */ + return 0; + } + + /* Check if the WinSock DLL supports 1.1+ */ + if (wsaData.wVersion != wVersionReq) { + /* No good WinSock DLL. */ + WSACleanup(); + iWinsockNeed = WSAVERNOTSUPPORTED; + return 0; + } + } + return 1; +} +#endif + static mms_io_t fallback_io = { @@ -454,7 +529,7 @@ size_t op_len = dest_len - 2; /* reserve 2 bytes for 0 termination */ if (iconv(url_conv, &ip, &ip_len, &op, &op_len) == (size_t)-1) { - lprintf("mms: Error converting uri to unicode: %s\n", strerror(errno)); + lprintf("mms: Error converting uri to unicode: %s\n", strerror(get_errno())); return 0; } @@ -1021,6 +1096,11 @@ if (!url) return NULL; +#ifdef _WIN32 + if (!mms_internal_winsock_load()) + return NULL; +#endif + /* FIXME: needs proper error-signalling work */ this = (mms_t*) malloc (sizeof (mms_t)); @@ -1272,18 +1352,11 @@ return this; fail: - if (this->s != -1) - close (this->s); - if (this->url) - free(this->url); - if (this->guri) - gnet_uri_delete(this->guri); - if (this->uri) - free(this->uri); + mms_close(this); + if (url_conv != (iconv_t)-1) iconv_close(url_conv); - free (this); return NULL; } @@ -1753,8 +1826,10 @@ void mms_close (mms_t *this) { + if (this == NULL) + return; if (this->s != -1) - close (this->s); + closesocket (this->s); if (this->url) free(this->url); if (this->guri) diff -r -u libmms-0.6-old/src/mms.h libmms-0.6-new/src/mms.h --- libmms-0.6-old/src/mms.h 2010-05-30 11:28:26 +0000 +++ libmms-0.6-new/src/mms.h 2010-09-20 13:04:20 +0000 @@ -34,7 +34,6 @@ #include #include -#include /* #include "xine_internal.h" */ diff -r -u libmms-0.6-old/src/mmsh.c libmms-0.6-new/src/mmsh.c --- libmms-0.6-old/src/mmsh.c 2010-05-31 10:13:04 +0000 +++ libmms-0.6-new/src/mmsh.c 2010-09-20 13:12:58 +0000 @@ -34,12 +34,22 @@ #include "config.h" #endif +#ifdef HAVE_WINSOCK2_H +#include +#endif + #include #include #include +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_NETDB_H #include +#endif #include #include #include @@ -60,6 +70,20 @@ #include "uri.h" #include "mms-common.h" +#ifdef WIN32 +#define set_errno(_err) WSASetLastError(_err) +#define get_errno() WSAGetLastError() +#define is_errno(_err) (WSAGetLastError() == (_err)) +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#else +#define set_errno(_err) errno = (_err) +#define get_errno() errno +#define is_errno(_err) (errno == (_err)) +#define closesocket(_s) close(_s) +#endif + /* #define USERAGENT "User-Agent: NSPlayer/7.1.0.3055\r\n" */ #define USERAGENT "User-Agent: NSPlayer/4.1.0.3856\r\n" #define CLIENTGUID "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}\r\n" @@ -81,8 +105,8 @@ #define SCRATCH_SIZE 1024 -#define SUCCESS 0 -#define ERROR 1 +#define MMSH_SUCCESS 0 +#define MMSH_ERROR 1 #define EOS 2 #define GOT_HEADER_N_DATA 3 @@ -218,16 +242,20 @@ { off_t len = 0, ret; /* lprintf("%d\n", fallback_io_select(data, socket, MMS_IO_READ_READY, 1000)); */ - errno = 0; + set_errno(0); while (len < num) { +#ifdef WIN32 + ret = (off_t)recv(socket, buf + len, num - len, 0); +#else ret = (off_t)read(socket, buf + len, num - len); +#endif if(ret == 0) break; /* EOS */ if(ret < 0) { lprintf("mmsh: read error @ len = %lld: %s\n", (long long int) len, - strerror(errno)); - switch(errno) + strerror(get_errno())); + switch(get_errno()) { case EAGAIN: continue; @@ -243,7 +271,11 @@ static off_t fallback_io_write(void *data, int socket, char *buf, off_t num) { +#ifdef WIN32 + return (off_t)send(socket, buf, num, 0); +#else return (off_t)write(socket, buf, num); +#endif } static int fallback_io_tcp_connect(void *data, const char *host, int port) @@ -251,7 +283,12 @@ struct hostent *h; int i, s; - +#ifdef BEOS + int on_state = 1; +#elif defined HAVE_WINSOCK2_H + unsigned long arg = 1; +#endif + h = gethostbyname(host); if (h == NULL) { lprintf("mmsh: unable to resolve host: %s\n", host); @@ -260,14 +297,25 @@ s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == -1) { - lprintf("mmsh: failed to create socket: %s\n", strerror(errno)); + lprintf("mmsh: failed to create socket: %s\n", strerror(get_errno())); return -1; } +/* set socket to non-blocking */ +#ifdef BEOS + if (setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(on)) == -1) { + return -1; + } +#elif defined WIN32 + if (ioctlsocket(s, FIONBIO, &arg)) { + return -1; + } +#else if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) & ~O_NONBLOCK) == -1) { - lprintf("mmsh: failed to set socket flags: %s\n", strerror(errno)); + lprintf("mmsh: failed to set socket flags: %s\n", strerror(get_errno())); return -1; } +#endif for (i = 0; h->h_addr_list[i]; i++) { struct in_addr ia; @@ -278,13 +326,13 @@ sin.sin_addr = ia; sin.sin_port = htons(port); - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==-1 && errno != EINPROGRESS) { + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==-1 && is_errno(EINPROGRESS)) { continue; } return s; } - close(s); + closesocket(s); return -1; } @@ -459,7 +507,7 @@ if (read_len == 0) return EOS; lprintf("mmsh: chunk header read failed, %d != %d\n", read_len, CHUNK_HEADER_LENGTH); - return ERROR; + return MMSH_ERROR; } this->chunk_type = LE_16 (&chunk_header[0]); this->chunk_length = LE_16 (&chunk_header[2]); @@ -485,7 +533,7 @@ read_len = io_read (io, this->s, ext_header, ext_header_len); if (read_len != ext_header_len) { lprintf("mmsh: extended header read failed. %d != %d\n", read_len, ext_header_len); - return ERROR; + return MMSH_ERROR; } } @@ -527,7 +575,7 @@ #endif this->chunk_length -= ext_header_len; - return SUCCESS; + return MMSH_SUCCESS; } static int get_header (mms_io_t *io, mmsh_t *this) { @@ -539,11 +587,11 @@ /* read chunk */ while (1) { - if ((ret = get_chunk_header(io, this)) == SUCCESS) { + if ((ret = get_chunk_header(io, this)) == MMSH_SUCCESS) { if (this->chunk_type == CHUNK_TYPE_ASF_HEADER) { if ((this->asf_header_len + this->chunk_length) > ASF_HEADER_SIZE) { lprintf ("mmsh: the asf header exceed %d bytes\n", ASF_HEADER_SIZE); - return ERROR; + return MMSH_ERROR; } else { len = io_read(io, this->s, this->asf_header + this->asf_header_len, this->chunk_length); @@ -552,7 +600,7 @@ if (len != this->chunk_length) { lprintf ("mmsh: asf header chunk read failed, %d != %d\n", len, this->chunk_length); - return ERROR; + return MMSH_ERROR; } } } else { @@ -572,13 +620,13 @@ if (len != this->chunk_length) { lprintf ("mmsh: asf data chunk read failed, %d != %d\n", len, this->chunk_length); - return ERROR; + return MMSH_ERROR; } else { /* check and 0 pad the first data chunk */ if (this->chunk_length > this->packet_length) { lprintf ("mmsh: chunk_length(%d) > packet_length(%d)\n", this->chunk_length, this->packet_length); - return ERROR; + return MMSH_ERROR; } /* explicit padding with 0 */ @@ -588,12 +636,12 @@ this->buf_size = this->packet_length; - return SUCCESS; + return MMSH_SUCCESS; } } else { /* unexpected packet type */ lprintf ("mmsh: unexpected chunk_type(0x%04x)\n", this->chunk_type); - return ERROR; + return MMSH_ERROR; } } @@ -832,6 +880,33 @@ return 0; } +#ifdef _WIN32 +static int iWinsockNeed = WSASYSNOTREADY; + +static int mmsh_internal_winsock_load(void) +{ + if (iWinsockNeed) { + WORD wVersionReq = MAKEWORD(1, 1); + WSADATA wsaData; + + iWinsockNeed = WSAStartup(wVersionReq, &wsaData); + if (iWinsockNeed != 0) { + /* Cannot load Winsock DLL. */ + return 0; + } + + /* Check if the WinSock DLL supports 1.1+ */ + if (wsaData.wVersion != wVersionReq) { + /* No good WinSock DLL. */ + WSACleanup(); + iWinsockNeed = WSAVERNOTSUPPORTED; + return 0; + } + } + return 1; +} +#endif + static int mmsh_connect_int (mms_io_t *io, mmsh_t *this, off_t seek, uint32_t time_seek) { int i; int video_stream = -1; @@ -845,7 +920,7 @@ /* Close exisiting connection (if any) and connect */ if (this->s != -1) - close(this->s); + closesocket(this->s); if (mmsh_tcp_connect(io, this)) { return 0; @@ -868,15 +943,15 @@ if (!get_answer (io, this)) goto fail; - /* Don't check for != SUCCESS as EOS is normal here too */ - if (get_header(io, this) == ERROR) + /* Don't check for != MMSH_SUCCESS as EOS is normal here too */ + if (get_header(io, this) == MMSH_ERROR) goto fail; interp_header(io, this); if (!this->packet_length || !this->num_stream_ids) goto fail; - close(this->s); + closesocket(this->s); /* choose the best quality for the audio stream */ /* i've never seen more than one audio stream */ @@ -983,7 +1058,7 @@ if (!get_answer (io, this)) goto fail; - if (get_header(io, this) != SUCCESS) + if (get_header(io, this) != MMSH_SUCCESS) goto fail; interp_header(io, this); @@ -1010,7 +1085,7 @@ } return 1; fail: - close(this->s); + closesocket(this->s); this->s = -1; return 0; } @@ -1023,6 +1098,11 @@ if (!url) return NULL; +#ifdef _WIN32 + if (!mmsh_internal_winsock_load()) + return NULL; +#endif + /* * initializatoin is essential here. the fail: label depends * on the various char * in our this structure to be @@ -1129,37 +1209,16 @@ gnet_uri_delete(proxy_uri); if (uri) gnet_uri_delete(uri); - if (this->s != -1) - close(this->s); - if (this->url) - free(this->url); - if (this->proxy_url) - free(this->proxy_url); - if (this->proto) - free(this->proto); - if (this->connect_host) - free(this->connect_host); - if (this->http_host) - free(this->http_host); - if (this->proxy_user) - free(this->proxy_user); - if (this->proxy_password) - free(this->proxy_password); - if (this->host_user) - free(this->host_user); - if (this->host_password) - free(this->host_password); - if (this->uri) - free(this->uri); - free(this); + mmsh_close (this); + return NULL; } static int get_media_packet (mms_io_t *io, mmsh_t *this) { int ret, len = 0; - if (get_chunk_header(io, this) == SUCCESS) { + if (get_chunk_header(io, this) == MMSH_SUCCESS) { switch (this->chunk_type) { case CHUNK_TYPE_END: /* this->chunk_seq_number: @@ -1171,7 +1230,7 @@ this->http_request_number = 1; if (!mmsh_connect_int (io, this, 0, 0)) - return ERROR; + return MMSH_ERROR; /* What todo with: current_pos ?? Also our chunk_seq_numbers will probably restart from 0! @@ -1193,9 +1252,9 @@ if (this->chunk_length != 0) { /* that's strange, don't know what to do */ lprintf("mmsh: non 0 sized reset chunk"); - return ERROR; + return MMSH_ERROR; } - if ((ret = get_header (io, this)) != SUCCESS) { + if ((ret = get_header (io, this)) != MMSH_SUCCESS) { lprintf("mmsh: failed to get header after reset chunk\n"); return ret; } @@ -1213,7 +1272,7 @@ default: lprintf("mmsh: unexpected chunk_type(0x%04x)\n", this->chunk_type); - return ERROR; + return MMSH_ERROR; } len = io_read (io, this->s, this->buf, this->chunk_length); @@ -1223,18 +1282,18 @@ if (this->chunk_length > this->packet_length) { lprintf("mmsh: chunk_length(%d) > packet_length(%d)\n", this->chunk_length, this->packet_length); - return ERROR; + return MMSH_ERROR; } memset(this->buf + this->chunk_length, 0, this->packet_length - this->chunk_length); this->buf_size = this->packet_length; - return SUCCESS; + return MMSH_SUCCESS; } else { lprintf("mmsh: media packet read error, %d != %d\n", len, this->chunk_length); - return ERROR; + return MMSH_ERROR; } } else if (ret == EOS) { return EOS; @@ -1292,9 +1351,9 @@ ret = get_media_packet (io, this); switch (ret) { - case SUCCESS: + case MMSH_SUCCESS: break; - case ERROR: + case MMSH_ERROR: lprintf ("mmsh: get_media_packet failed\n"); return total; case EOS: @@ -1359,7 +1418,7 @@ this->packet_length != orig_asf_packet_len) { lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n"); /* Its a different stream, so its useless! */ - close (this->s); + closesocket(this->s); this->s = -1; return this->current_pos = -1; } @@ -1401,7 +1460,7 @@ this->packet_length != orig_asf_packet_len) { lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n"); /* Its a different stream, so its useless! */ - close (this->s); + closesocket(this->s); this->s = -1; return this->current_pos = -1; } @@ -1453,7 +1512,7 @@ this->packet_length != orig_asf_packet_len) { lprintf("mmsh: AIIEEE asf header or packet length changed on re-open for seek\n"); /* Its a different stream, so its useless! */ - close (this->s); + closesocket(this->s); this->s = -1; this->current_pos = -1; return 0; @@ -1470,8 +1529,10 @@ } void mmsh_close (mmsh_t *this) { + if (this == NULL) + return; if (this->s != -1) - close(this->s); + closesocket(this->s); if (this->url) free(this->url); if (this->proxy_url) @@ -1492,8 +1553,8 @@ free(this->host_password); if (this->uri) free(this->uri); - if (this) - free (this); + + free (this); } diff -r -u libmms-0.6-old/src/mmsh.h libmms-0.6-new/src/mmsh.h --- libmms-0.6-old/src/mmsh.h 2010-05-30 11:28:26 +0000 +++ libmms-0.6-new/src/mmsh.h 2010-09-20 13:04:26 +0000 @@ -27,7 +27,6 @@ #include #include -#include #include "mmsio.h" #ifdef __cplusplus diff -r -u libmms-0.6-old/src/mmsio.h libmms-0.6-new/src/mmsio.h --- libmms-0.6-old/src/mmsio.h 2010-05-30 11:28:26 +0000 +++ libmms-0.6-new/src/mmsio.h 2010-09-20 13:04:38 +0000 @@ -1,6 +1,8 @@ #ifndef __MMS_IO_H__ #define __MMS_IO_H__ +#include + #include "mms_config.h" /* On 64 bit file offset capable systems, libmms' configure script adds