[xiph-commits] r2871 - in liboggplay/trunk: include/oggplay plugin
src/liboggplay
tahn at svn.annodex.net
tahn at svn.annodex.net
Thu Jun 7 21:20:54 PDT 2007
Author: tahn
Date: 2007-06-07 21:20:54 -0700 (Thu, 07 Jun 2007)
New Revision: 2871
Modified:
liboggplay/trunk/include/oggplay/oggplay.h
liboggplay/trunk/include/oggplay/oggplay_enums.h
liboggplay/trunk/include/oggplay/oggplay_reader.h
liboggplay/trunk/include/oggplay/oggplay_tools.h
liboggplay/trunk/plugin/plugin_gui_linux.c
liboggplay/trunk/plugin/plugin_gui_mac.c
liboggplay/trunk/plugin/plugin_oggplay.c
liboggplay/trunk/src/liboggplay/oggplay.c
liboggplay/trunk/src/liboggplay/oggplay_file_reader.c
liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.c
liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.h
Log:
Reworked the timeout for oggplay_initialise; it now has small "local" timeouts for each socket I/O call, and the plugin tracks the overall timeout of ~30s.
Also made a couple of simple utility functions; oggplay_millisleep and oggplay_sys_time_in_ms.
Modified: liboggplay/trunk/include/oggplay/oggplay.h
===================================================================
--- liboggplay/trunk/include/oggplay/oggplay.h 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/include/oggplay/oggplay.h 2007-06-08 04:20:54 UTC (rev 2871)
@@ -34,6 +34,7 @@
* oggplay.h
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
#ifndef __OGGPLAY_H__
@@ -68,8 +69,8 @@
oggplay_new_with_reader(OggPlayReader *reader, char *location);
OggPlayErrorCode
-oggplay_initialise(OggPlay *me, int timeout_in_ms);
-
+oggplay_initialise(OggPlay *me, int block);
+
OggPlayErrorCode
oggplay_set_source(OggPlay *OS, char *source);
Modified: liboggplay/trunk/include/oggplay/oggplay_enums.h
===================================================================
--- liboggplay/trunk/include/oggplay/oggplay_enums.h 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/include/oggplay/oggplay_enums.h 2007-06-08 04:20:54 UTC (rev 2871)
@@ -34,10 +34,11 @@
* oggplay_enums.h
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
-#ifndef __OGGSYNC_ENUMS_H__
-#define __OGGSYNC_ENUMS_H__
+#ifndef __OGGPLAY_ENUMS_H__
+#define __OGGPLAY_ENUMS_H__
typedef enum OggPlayErrorCode {
E_OGGPLAY_CONTINUE = 1,
Modified: liboggplay/trunk/include/oggplay/oggplay_reader.h
===================================================================
--- liboggplay/trunk/include/oggplay/oggplay_reader.h 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/include/oggplay/oggplay_reader.h 2007-06-08 04:20:54 UTC (rev 2871)
@@ -34,16 +34,17 @@
* oggplay_reader.h
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
-#ifndef __OGGSYNC_READER_H__
-#define __OGGSYNC_READER_H__
+#ifndef __OGGPLAY_READER_H__
+#define __OGGPLAY_READER_H__
struct _OggPlayReader;
typedef struct _OggPlayReader {
OggPlayErrorCode (*initialise)(struct _OggPlayReader * me, char * source,
- int timeout_in_ms);
+ int block);
OggPlayErrorCode (*destroy)(struct _OggPlayReader * me);
OggPlayErrorCode (*get_next_chunk)(struct _OggPlayReader *me,
unsigned char **position, int *size, int *base);
Modified: liboggplay/trunk/include/oggplay/oggplay_tools.h
===================================================================
--- liboggplay/trunk/include/oggplay/oggplay_tools.h 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/include/oggplay/oggplay_tools.h 2007-06-08 04:20:54 UTC (rev 2871)
@@ -31,9 +31,10 @@
*/
/*
- * oggplay.h
+ * oggplay_tools.h
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
#ifndef __OGGPLAY_TOOLS_H__
@@ -67,6 +68,12 @@
void
oggplay_yuv2bgr(OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb);
+ogg_int64_t
+oggplay_sys_time_in_ms();
+
+void
+oggplay_millisleep(long ms);
+
#ifdef __cplusplus
}
#endif
Modified: liboggplay/trunk/plugin/plugin_gui_linux.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_linux.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/plugin/plugin_gui_linux.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -16,7 +16,7 @@
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
- * Contributor(s): Shane Stephens
+ * Contributor(s): Shane Stephens, Michael Martin
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -437,8 +437,7 @@
g_signal_emit_by_name(info->window, "destroy-event", NULL, &result);
while (info->shutdown_gui) {
- struct timespec t = {0, 10000};
- nanosleep(&t, NULL);
+ oggplay_millisleep(10);
}
shut_oggplay(info->ogg_handle);
Modified: liboggplay/trunk/plugin/plugin_gui_mac.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_mac.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/plugin/plugin_gui_mac.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -105,26 +105,6 @@
/*
* -----------------------------------------------------------------------------
- * Helper functions
- * -----------------------------------------------------------------------------
- */
-
-static void
-millisleep(long ms) {
- struct timespec ts = {0, ms * 1000000};
- nanosleep(&ts, NULL);
-}
-
-static int64_t
-get_curr_time() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (int64_t)tv.tv_sec * 1000 + (int64_t)tv.tv_usec / 1000;
-}
-
-
-/*
- * -----------------------------------------------------------------------------
* Display thread functions
* -----------------------------------------------------------------------------
*/
@@ -369,9 +349,9 @@
PluginWindowInfo * info = (PluginWindowInfo *)_info;
ThreadData td;
- int64_t playback_target = 0;
bool paused = FALSE;
bool drop_video_frame = FALSE;
+ int64_t playback_target = 0;
int64_t time_ref;
int64_t cur_time;
int64_t offset;
@@ -446,7 +426,7 @@
*/
if (!have_video && !have_audio) {
free_oggplay_frame(info->oggplay_handle, &td.frame_data);
- millisleep(5);
+ oggplay_millisleep(5);
continue;
}
@@ -520,9 +500,9 @@
*/
if (cur_time == -1) {
if (playback_target == 0) {
- time_ref = get_curr_time();
+ time_ref = oggplay_sys_time_in_ms();
}
- cur_time = get_curr_time() - time_ref;
+ cur_time = oggplay_sys_time_in_ms() - time_ref;
}
/*
@@ -545,7 +525,7 @@
}
free_oggplay_frame(info->oggplay_handle, &td.frame_data);
- millisleep(offset);
+ oggplay_millisleep(offset);
} /* while (!info->shutdown_gui) */
@@ -677,7 +657,7 @@
*/
info->shutdown_gui = 1;
while (info->shutdown_gui) {
- millisleep(1);
+ oggplay_millisleep(1);
}
SEM_CLOSE(info->display_resize_sem);
Modified: liboggplay/trunk/plugin/plugin_oggplay.c
===================================================================
--- liboggplay/trunk/plugin/plugin_oggplay.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/plugin/plugin_oggplay.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -131,7 +131,32 @@
SEM_CREATE(pointers->sem, LIBOGGPLAY_BUFFER_SIZE);
SEM_SIGNAL(pointers->start_stop_sem);
- oggplay_initialise(player, 0);
+ /*
+ * Wrap the oggplay startup process in a ~30 sec timeout. If we tell
+ * oggplay_initialise() not to block, it will use non-blocking I/O
+ * calls and return if any operation takes longer than some small
+ * period of time to complete.
+ */
+ ogg_int64_t time_ref = oggplay_sys_time_in_ms();
+ while (1) {
+ OggPlayErrorCode res = oggplay_initialise(player, 0);
+ if (res == E_OGGPLAY_OK) {
+ break;
+ }
+ if (pointers->shutdown_oggplay) {
+ goto thread_shutdown;
+ }
+ if (res == E_OGGPLAY_TIMEOUT) {
+ if (oggplay_sys_time_in_ms() - time_ref < 30000) {
+ continue;
+ }
+ }
+ printf("Failed to initialise oggplay; error %d\n", res);
+ while (!pointers->shutdown_oggplay) {
+ oggplay_millisleep(10);
+ }
+ goto thread_shutdown;
+ }
for (i = 0; i < oggplay_get_num_tracks(player); i++) {
if (oggplay_get_track_type(player, i) == OGGZ_CONTENT_THEORA) {
@@ -182,7 +207,6 @@
SEM_WAIT(pointers->sem);
if (pointers->shutdown_oggplay) {
- pointers->shutdown_oggplay = 0;
break;
}
@@ -192,8 +216,10 @@
}
}
+thread_shutdown:
+ pointers->shutdown_oggplay = 0;
+
SEM_CLOSE(pointers->sem);
- //SEM_CLOSE(pointers->start_stop_sem);
oggplay_close(pointers->player);
free(pointers->location);
free(pointers);
@@ -252,25 +278,6 @@
/*
* we don't actually need to wait for the oggplay object to shut itself down.
*/
-
-#if 0
-#if defined(XP_UX)
- while (pointers->shutdown_oggplay) {
- struct timespec t = {0, 10000};
- nanosleep(&t, NULL);
- }
-#elif defined(XP_WIN)
- while (pointers->shutdown_oggplay) {
- Sleep(10);
- }
-#elif defined(XP_MACOSX)
- while (pointers->shutdown_oggplay) {
- struct timespec t = {0, 10000};
- nanosleep(&t, NULL);
- }
-#endif
-#endif
-
}
void
Modified: liboggplay/trunk/src/liboggplay/oggplay.c
===================================================================
--- liboggplay/trunk/src/liboggplay/oggplay.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/src/liboggplay/oggplay.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -31,9 +31,10 @@
*/
/*
- * oggsync.c
+ * oggplay.c
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
#include "oggplay_private.h"
@@ -42,6 +43,10 @@
#include <string.h>
#include <stdlib.h>
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
OggPlay *
oggplay_new_with_reader(OggPlayReader *reader, char *location) {
@@ -65,12 +70,12 @@
}
OggPlayErrorCode
-oggplay_initialise(OggPlay *me, int timeout_in_ms) {
+oggplay_initialise(OggPlay *me, int block) {
OggPlayErrorCode return_val;
int i;
- return_val = me->reader->initialise(me->reader, me->input_name, timeout_in_ms);
+ return_val = me->reader->initialise(me->reader, me->input_name, block);
if (return_val != E_OGGPLAY_OK) {
return return_val;
@@ -509,6 +514,10 @@
return E_OGGPLAY_BAD_OGGPLAY;
}
+ if (me->reader != NULL) {
+ me->reader->destroy(me->reader);
+ }
+
for (i = 0; i < me->num_tracks; i++) {
oggplay_callback_shutdown(me->decode_data[i]);
}
@@ -523,3 +532,27 @@
return E_OGGPLAY_OK;
}
+
+
+ogg_int64_t
+oggplay_sys_time_in_ms() {
+#ifdef WIN32
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ return ((ogg_int64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10000;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (ogg_int64_t)tv.tv_sec * 1000 + (ogg_int64_t)tv.tv_usec / 1000;
+#endif
+}
+
+void
+oggplay_millisleep(long ms) {
+#ifdef WIN32
+ Sleep(ms);
+#else
+ struct timespec ts = {0, ms * 1000000};
+ nanosleep(&ts, NULL);
+#endif
+}
Modified: liboggplay/trunk/src/liboggplay/oggplay_file_reader.c
===================================================================
--- liboggplay/trunk/src/liboggplay/oggplay_file_reader.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/src/liboggplay/oggplay_file_reader.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -34,6 +34,7 @@
* oggplay_file_reader.c
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
#include "oggplay_private.h"
@@ -43,11 +44,10 @@
#include <string.h>
OggPlayErrorCode
-oggplay_file_reader_initialise(OggPlayReader * opr, char * file_name,
- int timeout_in_ms) {
+oggplay_file_reader_initialise(OggPlayReader * opr, char * file_name, int block) {
OggPlayFileReader * me = (OggPlayFileReader *)opr;
- (void)timeout_in_ms; /* unused for file readers */
+ (void)block; /* unused for file readers */
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
Modified: liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.c
===================================================================
--- liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.c 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.c 2007-06-08 04:20:54 UTC (rev 2871)
@@ -34,6 +34,7 @@
* oggplay_tcp_reader.c
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
#include "oggplay_private.h"
@@ -65,305 +66,295 @@
#endif
-static void
-millisleep(long ms) {
-#ifdef WIN32
- Sleep(ms);
-#else
- struct timespec ts = {0, ms * 1000000};
- nanosleep(&ts, NULL);
-#endif
-}
-
-
-static ogg_int64_t
-curr_time_in_ms() {
+static int
+set_socket_blocking_state(OggPlayTCPReader *me, int is_blocking) {
#ifdef WIN32
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- return ((ogg_int64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10000;
+ u_long io_mode = !is_blocking;
+ if (ioctlsocket(me->socket, FIONBIO, &io_mode) == SOCKET_ERROR) {
#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (ogg_int64_t)tv.tv_sec * 1000 + (ogg_int64_t)tv.tv_usec / 1000;
+ if (fcntl(me->socket, F_SETFL, is_blocking ? 0 : O_NONBLOCK) == -1) {
#endif
+ return 0;
+ }
+ return 1;
}
-static void
-close_socket(OggPlayTCPReader *me) {
+#define START_TIMEOUT(ref) \
+ (ref) = oggplay_sys_time_in_ms()
- if (me->socket != INVALID_SOCKET) {
-#ifdef WIN32
-#ifdef HAVE_WINSOCK2
- shutdown(me->socket, SD_BOTH);
-#endif
- closesocket(me->socket);
- WSACleanup();
-#else
- close(me->socket);
-#endif
- me->socket = INVALID_SOCKET;
+#define RETURN_ON_TIMEOUT_OR_CONTINUE(ref) \
+ if (oggplay_sys_time_in_ms() - (ref) > 500) { \
+ return E_OGGPLAY_TIMEOUT; \
+ } else { \
+ oggplay_millisleep(10); \
+ continue; \
}
-}
-
OggPlayErrorCode
-oggplay_tcp_reader_initialise(OggPlayReader * opr, char * location,
- int timeout_in_ms) {
+oggplay_tcp_reader_initialise(OggPlayReader * opr, char * location, int block) {
- OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
+ OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
struct hostent * he;
struct sockaddr_in addr;
+ char * _location;
char * host;
char * path;
char * pos;
- int r;
- int offset;
- int port = 80;
int len;
- int has_http = 0;
- int remaining = TCP_READER_MAX_BUFFER_SIZE;
- char buf[1024];
+ int nbytes;
+ int has_http;
+ int remaining;
+ char http_request_header[1024];
ogg_int64_t time_ref;
-#ifdef WIN32
- u_long io_mode;
-#endif
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
-
- /*
- * The easiest way to implement a no-timeout option is to make the
- * timeout ridiculously long (like 24.8 days...)
- */
- time_ref = curr_time_in_ms();
- if (timeout_in_ms <= 0) {
- timeout_in_ms = 0x7fffffff;
+ if (me->state == OTRS_INIT_COMPLETE) {
+ return E_OGGPLAY_OK;
}
/*
- * extract the host name and the path from the location
+ * Create the socket.
*/
- len = strlen(location);
- me->location = (char*)malloc(len + 1);
- strcpy(me->location, location);
-
+ if (me->state == OTRS_UNINITIALISED) {
+ assert(me->socket == INVALID_SOCKET);
#ifdef WIN32
#ifdef HAVE_WINSOCK2
- WORD wVersionRequested = MAKEWORD(2,2);
+ WORD wVersionRequested = MAKEWORD(2,2);
#else
- WORD wVersionRequested = MAKEWORD(1,1);
+ WORD wVersionRequested = MAKEWORD(1,1);
#endif
- WSADATA wsaData;
- if (WSAStartup(wVersionRequested, &wsaData) == -1) {
- printf("Socket open error\n");
- return E_OGGPLAY_SOCKET_ERROR;
- }
- if (wsaData.wVersion != wVersionRequested) {
- printf("Incorrect winsock version [%d]\n", wVersionRequested);
- WSACleanup();
- return E_OGGPLAY_SOCKET_ERROR;
- }
+ WSADATA wsaData;
+ if (WSAStartup(wVersionRequested, &wsaData) == -1) {
+ printf("Socket open error\n");
+ return E_OGGPLAY_SOCKET_ERROR;
+ }
+ if (wsaData.wVersion != wVersionRequested) {
+ printf("Incorrect winsock version [%d]\n", wVersionRequested);
+ WSACleanup();
+ return E_OGGPLAY_SOCKET_ERROR;
+ }
#endif
- me->socket = socket(PF_INET, SOCK_STREAM, 0);
- if (me->socket == INVALID_SOCKET) {
+ me->socket = socket(PF_INET, SOCK_STREAM, 0);
+ if (me->socket == INVALID_SOCKET) {
+ printf("Could not create socket\n");
#ifdef WIN32
- WSACleanup();
+ WSACleanup();
#endif
- return E_OGGPLAY_SOCKET_ERROR;
+ return E_OGGPLAY_SOCKET_ERROR;
+ }
+
+ me->state = OTRS_SOCKET_CREATED;
}
- /*
- * Set the socket to non-blocking mode.
+ /*
+ * If required, set the socket to non-blocking mode so we can
+ * timeout and return control to the caller.
*/
-#ifdef WIN32
- io_mode = 1;
- if (ioctlsocket(me->socket, FIONBIO, &io_mode) == SOCKET_ERROR) {
-#else
- if (fcntl(me->socket, F_SETFL, O_NONBLOCK) == -1) {
-#endif
- close_socket(me);
- return E_OGGPLAY_SOCKET_ERROR;
+ if (!block) {
+ if (!set_socket_blocking_state(me, 0)) {
+ return E_OGGPLAY_SOCKET_ERROR;
+ }
}
- if (strncmp(me->location, "http://", 7) == 0) {
- path = strchr(me->location + 7, '/');
+ /*
+ * Extract the host name and the path from the location.
+ */
+ len = strlen(location);
+ _location = (char*)malloc(len + 2);
+ strcpy(_location, location);
+
+ if (strncmp(_location, "http://", 7) == 0) {
+ path = strchr(_location + 7, '/');
has_http = 1;
} else {
- path = strchr(me->location, '/');
+ path = strchr(_location, '/');
+ has_http = 0;
}
-
+
if (path == NULL) {
- me->location = (char*)realloc(me->location, len + 2);
- me->location[len] = '/';
- me->location[len + 1] = '\0';
- path = me->location + len;
- len += 1;
+ _location[len] = '/';
+ _location[len + 1] = '\0';
+ path = _location + len;
}
if (has_http) {
- host = (char*)malloc((path - me->location) - 6);
- strncpy(host, me->location + 7, (path - me->location) - 7);
- host[(path - me->location) - 7] = '\0';
+ host = (char*)malloc((path - _location) - 6);
+ strncpy(host, _location + 7, (path - _location) - 7);
+ host[(path - _location) - 7] = '\0';
} else {
- host = (char*)malloc((path - me->location) + 1);
- strncpy(host, me->location, path - me->location);
- host[path - me->location] = '\0';
+ host = (char*)malloc((path - _location) + 1);
+ strncpy(host, _location, path - _location);
+ host[path - _location] = '\0';
}
+ printf("host: %s, path: %s\n", host, path);
+
+ /*
+ * Prepare the HTTP request header now, so we can free all our
+ * allocated memory before returning on any errors.
+ */
+ snprintf(http_request_header, 1024,
+ "GET %s HTTP/1.0\n"
+ "Host: %s\n"
+ "User-Agent: AnnodexFirefoxPlugin/0.1\n"
+ "Accept: */*\n"
+ "Connection: Keep-Alive\n\n", path, host);
+
he = gethostbyname(host);
+ free(_location);
+ free(host);
if (he == NULL) {
- printf("Host %s not found\n", host);
- close_socket(me);
+ printf("Host not found\n");
return E_OGGPLAY_BAD_INPUT;
}
-
- printf("host: %s, path: %s\n", host, path);
-
memcpy(&addr.sin_addr.s_addr, he->h_addr, he->h_length);
addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
-
+ addr.sin_port = htons(80);
+
/*
- * connect to the host
+ * Connect to the host.
*/
- while (connect(me->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
- if (errno == EINPROGRESS || errno == EALREADY) {
- if ((int)(curr_time_in_ms() - time_ref) > timeout_in_ms) {
- close_socket(me);
- return E_OGGPLAY_TIMEOUT;
+ if (me->state == OTRS_SOCKET_CREATED) {
+ START_TIMEOUT(time_ref);
+ while (connect(me->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (errno == EINPROGRESS || errno == EALREADY
+#ifdef WIN32
+ /* see http://msdn2.microsoft.com/en-us/library/ms737625.aspx */
+ || errno == EWOULDBLOCK || errno == EINVAL
+#endif
+ ) {
+ RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
+ } else if (errno == EISCONN) {
+ break;
}
- millisleep(1);
- continue;
- } else if (errno == EISCONN) {
- break;
+ printf("Could not connect to host; error code is %d\n", errno);
+ return (errno == ETIMEDOUT) ? E_OGGPLAY_TIMEOUT : E_OGGPLAY_SOCKET_ERROR;
}
- printf("Could not connect to host; error code is %d\n", errno);
- close_socket(me);
- return (errno == ETIMEDOUT) ? E_OGGPLAY_TIMEOUT : E_OGGPLAY_SOCKET_ERROR;
+ me->state = OTRS_CONNECTED;
}
/*
- * prepare and send an HTTP request header
+ * Send the HTTP request header.
+ *
+ * If this times out after sending some, but not all, of the request header,
+ * we'll end up sending the entire header string again. This is probably not
+ * the best idea, so we may want to rework it at some time...
*/
- snprintf(buf, 1024,
- "GET %s HTTP/1.0\n"
- "Host: %s\n"
- "User-Agent: AnnodexFirefoxPlugin/0.1\n"
- "Accept: */*\n"
- "Connection: Keep-Alive\n\n", path, host);
-
- pos = buf;
- len = strlen(buf);
- while (1) {
+ if (me->state == OTRS_CONNECTED) {
+ pos = http_request_header;
+ len = strlen(http_request_header);
+ START_TIMEOUT(time_ref);
+ while (1) {
#if WIN32
- r = send(me->socket, pos, len, 0);
+ nbytes = send(me->socket, pos, len, 0);
#else
- r = write(me->socket, pos, len);
+ nbytes = write(me->socket, pos, len);
#endif
- if (r < 0) {
- if (errno == EAGAIN) {
- if ((int)(curr_time_in_ms() - time_ref) > timeout_in_ms) {
- close_socket(me);
- return E_OGGPLAY_TIMEOUT;
+ if (nbytes < 0) {
+ if (errno == EAGAIN) {
+ RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
}
- millisleep(1);
- continue;
+ return E_OGGPLAY_SOCKET_ERROR;
+ } else if (nbytes >= len) {
+ break;
}
- close_socket(me);
- return E_OGGPLAY_SOCKET_ERROR;
- } else if (r >= len) {
- break;
+ pos += nbytes;
+ len -= nbytes;
}
- pos += r;
- len -= r;
+ me->state = OTRS_SENT_HEADER;
}
/*
- * fill the buffers before returning
- */
- me->buffer = (unsigned char*)malloc (TCP_READER_MAX_BUFFER_SIZE);
- me->buffer_size = 0;
-
- /*
- * strip out the HTTP response by finding the first Ogg packet
+ * Strip out the HTTP response by finding the first Ogg packet.
*/
- while (1) {
+ if (me->state == OTRS_SENT_HEADER) {
+ int offset;
+
+ if (me->buffer == NULL) {
+ me->buffer = (unsigned char*)malloc(TCP_READER_MAX_BUFFER_SIZE);
+ me->buffer_size = 0;
+ }
+
+ START_TIMEOUT(time_ref);
+ while (1) {
+ remaining = TCP_READER_MAX_BUFFER_SIZE - me->buffer_size;
#if WIN32
- r = recv(me->socket, (char*)(me->buffer + me->buffer_size), remaining - 1, 0);
+ nbytes = recv(me->socket, (char*)(me->buffer + me->buffer_size), remaining - 1, 0);
#else
- r = read(me->socket, (char*)(me->buffer + me->buffer_size), remaining - 1);
+ nbytes = read(me->socket, (char*)(me->buffer + me->buffer_size), remaining - 1);
#endif
- if (r < 0) {
- if (errno == EAGAIN) {
- if ((int)(curr_time_in_ms() - time_ref) > timeout_in_ms) {
- close_socket(me);
- return E_OGGPLAY_TIMEOUT;
+ if (nbytes < 0) {
+ if (errno == EAGAIN) {
+ RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
}
- millisleep(1);
- continue;
+ return E_OGGPLAY_SOCKET_ERROR;
+ } else if (nbytes == 0) {
+ /*
+ * End-of-file is an error here, because we should at least be able
+ * to read a complete HTTP response header.
+ */
+ return E_OGGPLAY_END_OF_FILE;
}
- close_socket(me);
- return E_OGGPLAY_SOCKET_ERROR;
- } else if (r == 0) {
- close_socket(me);
- return E_OGGPLAY_END_OF_FILE;
+ me->buffer[me->buffer_size + nbytes] = '\0';
+ pos = strstr((char *)(me->buffer), "OggS");
+ if (pos != NULL) {
+ break;
+ }
+ /* TODO: make this more robust */
+ if (strncmp((char *)me->buffer, "HTTP/1.1 200 OK", 15) != 0 &&
+ strncmp((char *)me->buffer, "HTTP/1.0 200 OK", 15) != 0) {
+ return E_OGGPLAY_BAD_INPUT;
+ }
+ if (nbytes > 4) {
+ memmove(me->buffer, me->buffer + nbytes - 4, 4);
+ me->buffer_size = 4;
+ } else {
+ me->buffer_size = nbytes;
+ }
}
- me->buffer[r] = '\0';
- pos = strstr((char *)(me->buffer), "OggS");
- if (pos == NULL) {
- memmove(me->buffer, me->buffer + r - 4, 4);
- me->buffer_size = 4;
- remaining = TCP_READER_MAX_BUFFER_SIZE - 4;
- } else {
- break;
- }
+ offset = pos - (char *)(me->buffer);
+ memmove(me->buffer, pos, nbytes - offset);
+ me->buffer_size = nbytes - offset;
+
+ me->state = OTRS_HTTP_RESPONDED;
}
- offset = pos - (char *)(me->buffer);
- memmove(me->buffer, pos, r - offset);
- me->buffer_size = r - offset;
- remaining = TCP_READER_MAX_BUFFER_SIZE - me->buffer_size;
-
/*
- * read in some more data
+ * Read in enough data to fill the buffer.
*/
- while (remaining > 0) {
+ if (me->state == OTRS_HTTP_RESPONDED) {
+ remaining = TCP_READER_MAX_BUFFER_SIZE - me->buffer_size;
+ START_TIMEOUT(time_ref);
+ while (remaining > 0) {
#ifdef WIN32
- r = recv(me->socket, (char*)(me->buffer + me->buffer_size), remaining, 0);
+ nbytes = recv(me->socket, (char*)(me->buffer + me->buffer_size), remaining, 0);
#else
- r = read(me->socket, me->buffer + me->buffer_size, remaining);
+ nbytes = read(me->socket, me->buffer + me->buffer_size, remaining);
#endif
- if (r < 0) {
- if (errno == EAGAIN) {
- if ((int)(curr_time_in_ms() - time_ref) > timeout_in_ms) {
- close_socket(me);
- return E_OGGPLAY_TIMEOUT;
+ if (nbytes < 0) {
+ if (errno == EAGAIN) {
+ RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
}
- millisleep(1);
- continue;
+ return E_OGGPLAY_SOCKET_ERROR;
+ } else if (nbytes == 0) {
+ /*
+ * End-of-file is *not* an error here, it's just a really small file.
+ */
+ break;
}
- close_socket(me);
- return E_OGGPLAY_SOCKET_ERROR;
- } else if (r == 0) {
- break;
+ me->buffer_size += nbytes;
+ remaining -= nbytes;
}
- me->buffer_size += r;
- remaining -= r;
+ me->state = OTRS_INIT_COMPLETE;
}
- /*
+ /*
* Set the socket back to blocking mode.
*/
-#ifdef WIN32
- io_mode = 0;
- if (ioctlsocket(me->socket, FIONBIO, &io_mode) == SOCKET_ERROR) {
-#else
- if (fcntl(me->socket, F_SETFL, 0) == -1) {
-#endif
- close_socket(me);
+ if (!set_socket_blocking_state(me, 1)) {
return E_OGGPLAY_SOCKET_ERROR;
}
@@ -376,7 +367,18 @@
OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
- close_socket(me);
+ if (me->socket != INVALID_SOCKET) {
+#ifdef WIN32
+#ifdef HAVE_WINSOCK2
+ shutdown(me->socket, SD_BOTH);
+#endif
+ closesocket(me->socket);
+ WSACleanup();
+#else
+ close(me->socket);
+#endif
+ }
+
free(me->buffer);
free(me);
return E_OGGPLAY_OK;
@@ -423,7 +425,6 @@
if (r < 0) {
return E_OGGPLAY_SOCKET_ERROR;
} else if (r == 0) {
- close_socket(me);
return E_OGGPLAY_END_OF_FILE;
}
@@ -494,13 +495,14 @@
OggPlayTCPReader * me = (OggPlayTCPReader *)malloc (sizeof (OggPlayTCPReader));
- me->location = NULL;
+ me->state = OTRS_UNINITIALISED;
me->socket = INVALID_SOCKET;
+ me->buffer = NULL;
+ me->buffer_size = 0;
me->current_position = 0;
me->functions.initialise = &oggplay_tcp_reader_initialise;
me->functions.destroy = &oggplay_tcp_reader_destroy;
-
me->functions.get_next_chunk = &oggplay_tcp_reader_get_next_chunk;
me->functions.mark_chunk_consumed = &oggplay_tcp_reader_mark_chunk_consumed;
Modified: liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.h
===================================================================
--- liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.h 2007-06-08 04:14:46 UTC (rev 2870)
+++ liboggplay/trunk/src/liboggplay/oggplay_tcp_reader.h 2007-06-08 04:20:54 UTC (rev 2871)
@@ -31,21 +31,31 @@
*/
/*
- * oggsync_tcp_reader.h
+ * oggplay_tcp_reader.h
*
* Shane Stephens <shane.stephens at annodex.net>
+ * Michael Martin
*/
-#ifndef __OGGSYNC_FILE_READER_H__
-#define __OGGSYNC_FILE_READER_H__
+#ifndef __OGGPLAY_FILE_READER_H__
+#define __OGGPLAY_FILE_READER_H__
#include <stdio.h>
#define TCP_READER_MAX_BUFFER_SIZE 16384
+typedef enum {
+ OTRS_UNINITIALISED,
+ OTRS_SOCKET_CREATED,
+ OTRS_CONNECTED,
+ OTRS_SENT_HEADER,
+ OTRS_HTTP_RESPONDED,
+ OTRS_INIT_COMPLETE
+} OPTCPReaderState;
+
typedef struct {
OggPlayReader functions;
- char * location;
+ OPTCPReaderState state;
#ifdef _WIN32
SOCKET socket;
#else
More information about the commits
mailing list