Menu

Diff of /trunk/php-java-bridge/protocol.c [r436] .. [r437]  Maximize  Restore

Switch to side-by-side view

--- a/trunk/php-java-bridge/protocol.c
+++ b/trunk/php-java-bridge/protocol.c
@@ -48,28 +48,31 @@
 /**
  * Send the packet to the server
  */
-static void send_data(proxyenv *env, char *data, size_t size) {
+static short send_data(proxyenv *env, char *data, size_t size) {
   size_t s=0; ssize_t n=0;
  res: 
   errno=0;
   while((size>s)&&((n=(*env)->f_send(env, data+s, size-s)) > 0)) 
 	s+=n;
   if(size>s && !n && errno==EINTR) goto res; // Solaris, see INN FAQ
-}
-
-static void add_header(proxyenv *env, size_t *size, char*header, size_t header_length) {
-  if(!header_length) return;
+  return n!=-1;
+}
+
+static short add_header(proxyenv *env, size_t *size, char*header, size_t header_length) {
+  if(!header_length) return 1;
 
   if(*size+header_length<(*env)->send_size) {
 	memmove((*env)->send+header_length, (*env)->send, *size);
 	memcpy(((*env)->send), header, header_length);
 	*size+=header_length;
+	return 1;
   } else {
-	send_data(env, header, header_length);
-  }
-}
-
-static void end(proxyenv *env) {
+	return send_data(env, header, header_length);
+  }
+}
+
+static short end(proxyenv *env) {
+  short success;
   size_t size = (*env)->send_len;
   char *servlet_context;
   char *context;
@@ -91,13 +94,12 @@
 	assert(!(*env)->peer_redirected || ((*env)->peer_redirected && (((*env)->peer0)==-1)));
 	header_length=EXT_GLOBAL(snprintf) (header, sizeof(header), "PUT %s HTTP/1.1\r\nHost: localhost\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\nContent-Length: %lu\r\nX_JAVABRIDGE_CHANNEL: %s\r\nX_JAVABRIDGE_CONTEXT: %s\r\n\r\n%c", servlet_context, (unsigned long)(size+1), EXT_GLOBAL(get_channel)(TSRMLS_C), getSessionFactory(env), mode);
 
-	add_header(env, &size, header, header_length);
+	success = add_header(env, &size, header, header_length);
   } else {						/* re-directed */
-	add_header(env, &size, context, context_length);
-  }
-  send_data(env, (char*)(*env)->send, size);
-
-  (*env)->send_len=0;
+	success = add_header(env, &size, context, context_length);
+  }
+  if(success) success = send_data(env, (char*)(*env)->send, size);
+  return success;
 }
 
 static char *get_cookies(zval *val, proxyenv *env) {
@@ -127,7 +129,8 @@
  * Sends override_redirect and cookies
  * @see check_context
  */
-static void end_session(proxyenv *env) {
+static short end_session(proxyenv *env) {
+  short success;
   size_t size = (*env)->send_len;
   zval val;
   int peer0 = (*env)->peer0;
@@ -142,18 +145,38 @@
   
   header_length=EXT_GLOBAL(snprintf) (header, sizeof(header), "PUT %s HTTP/1.1\r\nHost: localhost\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\nContent-Length: %lu\r\nX_JAVABRIDGE_REDIRECT: %d\r\n%sX_JAVABRIDGE_CHANNEL: %s\r\nX_JAVABRIDGE_CONTEXT: %s\r\n\r\n%c", (*env)->servlet_context_string, (unsigned long)(size+1), override_redirect, get_cookies(&val, env), EXT_GLOBAL(get_channel)(TSRMLS_C), getSessionFactory(env), mode);
 
-  add_header(env, &size, header, header_length);
-  send_data(env, (char*)(*env)->send, size);
-
+  success = add_header(env, &size, header, header_length);
+  if(success) success = send_data(env, (char*)(*env)->send, size);
+  return success;
+}
+
+/**
+ * Send out the data to the back-end.
+ * @param env The proxyenv
+ * @return 1 on success, 0 if the connection the back-end is lost
+ */
+static short finish(proxyenv *env) {
+  short success = (*env)->finish(env);
+  if(!success) { (*env)->connection_is_closed = 1; return 0; }
   (*env)->send_len=0;
-}
-
-static void flush(proxyenv *env) {
-  (*env)->finish(env);
-  (*env)->handle(env);
-}
-
-void protocol_end (proxyenv *env) {
+  return 1;
+}
+
+/**
+ * Send out the data to the back-end and read the response.
+ * @param env The proxyenv
+ * @return 1 on success, 0 if the connection the back-end is lost
+ */
+static short flush(proxyenv *env) {
+  short success;
+  if((*env)->connection_is_closed) return 0;
+  success = finish(env);
+  if(success) (*env)->handle(env);
+  return success;
+}
+
+static short end_connection (proxyenv *env) {
+  short success;
   char *servlet_context;
   short context_length = 0;
   char *context;
@@ -162,8 +185,10 @@
 
   if((*env)->must_reopen==2) context = get_context(env, kontext, &context_length);
   (*env)->must_reopen=0;
+  (*env)->finish=end;
 
   TSRMLS_FETCH();
+
   servlet_context = EXT_GLOBAL (get_servlet_context) (TSRMLS_C);
 
   if(!(*env)->is_local && servlet_context) {
@@ -174,13 +199,13 @@
 
 	header_length=EXT_GLOBAL(snprintf) (header, sizeof(header), "PUT %s HTTP/1.1\r\nHost: localhost\r\nConnection: Close\r\nContent-Type: text/html\r\nContent-Length: 0\r\nX_JAVABRIDGE_CONTEXT: %s\r\n\r\n", servlet_context, getSessionFactory(env));
 
-	add_header(env, &size, header, header_length);
-	send_data(env, (char*)(*env)->send, size);
+	success = add_header(env, &size, header, header_length);
+	if(success) success = send_data(env, (char*)(*env)->send, size);
   } else {						/* re-directed */
-	add_header(env, &size, context, context_length);
-	send_data(env, (char*)(*env)->send, size);
-  }
-  (*env)->send_len=0;
+	success = add_header(env, &size, context, context_length);
+	if(success) success = send_data(env, (char*)(*env)->send, size);
+  }
+  return success;
 }
 static ssize_t send_async(proxyenv*env, const void*buf, size_t length) {
   return (ssize_t)fwrite(buf, 1ul, length, (*env)->async_ctx.peer);
@@ -261,6 +286,8 @@
 	  int sock = socket (PF_INET, SOCK_STREAM, 0);
 	  struct sockaddr *saddr = &(*env)->orig_peer_saddr;
 	  if (-1!=sock) {
+		static const int true = 1;
+		setsockopt(sock, 0x6, TCP_NODELAY, (void*)&true, sizeof true);
 		if (-1!=connect(sock, saddr, sizeof (struct sockaddr))) {
 		  (*env)->peer0 = (*env)->peer;
 		  (*env)->peer = sock;
@@ -356,12 +383,12 @@
    (*env)->send_len+=EXT_GLOBAL(snprintf) ((char*)((*env)->send+(*env)->send_len), flen, "<C v=\"%s\" p=\"%c\" i=\"%ld\">", name, createInstance, (long)((*env)->async_ctx.result=result));
    assert((*env)->send_len<=(*env)->send_size);
  }
- static void CreateObjectEnd(proxyenv *env) {
+ static short CreateObjectEnd(proxyenv *env) {
    size_t flen;
    GROW(FLEN);
    (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "</C>");
    assert((*env)->send_len<=(*env)->send_size);
-   flush(env);
+   return flush(env);
  }
  static void InvokeBegin(proxyenv *env, long object, char*method, size_t len, char property, void* result) {
    size_t flen;
@@ -371,12 +398,12 @@
    (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "<I v=\"%ld\" m=\"%s\" p=\"%c\" i=\"%ld\">", object, method, property, (long)((*env)->async_ctx.result=result));
    assert((*env)->send_len<=(*env)->send_size);
  }
- static void InvokeEnd(proxyenv *env) {
+ static short InvokeEnd(proxyenv *env) {
    size_t flen;
    GROW(FLEN);
    (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "</I>");
    assert((*env)->send_len<=(*env)->send_size);
-   flush(env);
+   return flush(env);
  }
 
  static void ResultBegin(proxyenv *env, void*result) {
@@ -390,17 +417,19 @@
    GROW(FLEN);
    (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "</R>");
    assert((*env)->send_len<=(*env)->send_size);
-   end(env);
- }
-
- static void EndConnection(proxyenv *env, char property) {
-   size_t flen;
-   assert(property=='A' || property=='E');
-   GROW(FLEN);
-   (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "<F p=\"%c\"/>", property);
-   assert((*env)->send_len<=(*env)->send_size);
-   flush(env);
- }
+   finish(env);
+ }
+
+static short EndConnection(proxyenv *env, char property) {
+  size_t flen;
+  assert(property=='A' || property=='E');
+  GROW(FLEN);
+  (*env)->send_len+=EXT_GLOBAL(snprintf)((char*)((*env)->send+(*env)->send_len), flen, "<F p=\"%c\"/>", property);
+  assert((*env)->send_len<=(*env)->send_size);
+
+  (*env)->finish=end_connection;
+  return flush(env);
+}
 
  static void String(proxyenv *env, char*name, size_t _len) {
    size_t flen;
@@ -512,15 +541,15 @@
  
 
 static void close_connection(proxyenv *env TSRMLS_DC) {
+  short is_closed = 0;
   if(env && *env) {
 	if((*env)->peer!=-1) {
 	  /* end servlet session */
-	  (*env)->writeEndConnection(env, 'E');
-	  protocol_end(env);
+	  if(!(*env)->connection_is_closed) (*env)->writeEndConnection(env, 'E');
 	  close((*env)->peer);
-	  if((*env)->peerr!=-1) close((*env)->peerr);
-	  if((*env)->peer0!=-1) close((*env)->peer0);
 	}
+	if((*env)->peerr!=-1) close((*env)->peerr);
+	if((*env)->peer0!=-1) close((*env)->peer0);
 	if((*env)->s) free((*env)->s);
 	if((*env)->send) free((*env)->send);
 	if((*env)->server_name) free((*env)->server_name);
@@ -535,12 +564,15 @@
 	EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
   }
 }
-static void recycle_connection(proxyenv *env TSRMLS_DC) {
+static short recycle_connection(proxyenv *env TSRMLS_DC) {
   if(env && *env) {
+	if((*env)->connection_is_closed) return 0;
 	if((*env)->peer!=-1) {
-	  /* end servlet session */
-	  (*env)->writeEndConnection(env, 'A');
-	  protocol_end(env);
+
+	  if(!(*env)->writeEndConnection(env, 'A')) { 
+		(*env)->connection_is_closed=1;
+		return 0;
+	  }
 	}
 	EXT_GLOBAL(save_cfg)(env TSRMLS_CC);
 	EXT_GLOBAL(destroy_cloned_cfg)(TSRMLS_C);
@@ -550,13 +582,14 @@
 	  (*env)->current_servlet_ctx = 0; 
 	}
   }
-}
-void EXT_GLOBAL(close_connection)(proxyenv**penv, short persistent_connection TSRMLS_DC) {
-  if(persistent_connection) 
-	recycle_connection(*penv TSRMLS_CC);
-  else
-	close_connection(*penv TSRMLS_CC);
+  return 1;
+}
+short EXT_GLOBAL(close_connection)(proxyenv**penv, short persistent_connection TSRMLS_DC) {
+  int success = 1;
+  if(persistent_connection) success = recycle_connection(*penv TSRMLS_CC);
+  if(!persistent_connection || !success) close_connection(*penv TSRMLS_CC);
   *penv=0;						/* a copy should already be in connections */
+  return success;
 }
 proxyenv *EXT_GLOBAL(createSecureEnvironment) (int peer, void (*handle_request)(proxyenv *env), void (*handle_cached)(proxyenv *env), char *server_name, short is_local, struct sockaddr *saddr) {
    proxyenv *env;  
@@ -594,6 +627,7 @@
 
    (*env)->server_name = server_name;
    (*env)->must_reopen = 0;
+   (*env)->connection_is_closed = 0;
    (*env)->current_servlet_ctx = 
 	 (*env)->servlet_ctx = (*env)->servlet_context_string = 0;
    (*env)->backend_has_session_proxy = 0;
@@ -621,6 +655,7 @@
    (*env)->writePairBegin_n=PairBegin_n;
    (*env)->writePairEnd=PairEnd;
    (*env)->writeUnref=Unref;
+
    (*env)->writeEndConnection=EndConnection;
    (*env)->finish=end;