From c54140739bcb0d3eb06779eb2bf84b06c1d10833 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zden=C4=9Bk=20Salvet?= Date: Tue, 24 Mar 2009 17:57:31 +0000 Subject: [PATCH] Add back notification pool changes. --- org.glite.lb.client/src/connection.c | 212 ++++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/org.glite.lb.client/src/connection.c b/org.glite.lb.client/src/connection.c index d63bb98..a8f8574 100644 --- a/org.glite.lb.client/src/connection.c +++ b/org.glite.lb.client/src/connection.c @@ -50,6 +50,35 @@ int CloseConnection(edg_wll_Context ctx, int conn_index) } +int CloseConnectionNotif(edg_wll_Context ctx) +{ + /* close connection and free its structures */ + int cIndex,ret = 0; + + + cIndex = ctx->connNotif->connToUse; + + assert(ctx->connNotif->connOpened); + + if (ctx->connNotif->connPool[cIndex].gss.sock >= 0) + edg_wll_gss_close(&ctx->connNotif->connPool[cIndex].gss, &ctx->p_tmp_timeout); // always returns 0 + if (ctx->connNotif->connPool[cIndex].gsiCred != NULL) + if ( (ret = edg_wll_gss_release_cred(&ctx->connNotif->connPool[cIndex].gsiCred, NULL)) ) + edg_wll_SetError(ctx,ret,"error in edg_wll_gss_release_cred()"); + free(ctx->connNotif->connPool[cIndex].peerName); + free(ctx->connNotif->connPool[cIndex].buf); + free(ctx->connNotif->connPool[cIndex].bufOut); + free(ctx->connNotif->connPool[cIndex].certfile); + + memset(ctx->connNotif->connPool + cIndex, 0, sizeof(edg_wll_ConnPool)); + ctx->connNotif->connPool[cIndex].gss.sock = -1; + + ctx->connNotif->connOpened--; + + return edg_wll_Error(ctx,NULL,NULL); +} + + int ConnectionIndex(edg_wll_Context ctx, const char *name, int port) { @@ -99,7 +128,6 @@ int ConnectionIndex(edg_wll_Context ctx, const char *name, int port) } - int AddConnection(edg_wll_Context ctx, char *name, int port) { int i,index = -1; @@ -126,6 +154,25 @@ int AddConnection(edg_wll_Context ctx, char *name, int port) } +int SetFreeConnectionIndexNotif(edg_wll_Context ctx) +{ + int i; + + + ctx->connNotif->connToUse = -1; + + for (i = 0; i < ctx->connNotif->poolSize; i++) + if (ctx->connNotif->connPool[i].gss.sock == -1) { + ctx->connNotif->connToUse = i; + ctx->connNotif->connOpened++; + assert(!ctx->connNotif->connPool[i].buf); + break; + } + + return ctx->connNotif->connToUse; +} + + int ReleaseConnection(edg_wll_Context ctx, char *name, int port) { @@ -166,6 +213,34 @@ int ReleaseConnection(edg_wll_Context ctx, char *name, int port) } +int ReleaseConnectionNotif(edg_wll_Context ctx) +{ + int i, index = 0; + long min; + + + edg_wll_ResetError(ctx); + if (ctx->connNotif->connOpened == 0) return 0; /* nothing to release */ + + min = ctx->connNotif->connPool[0].lastUsed.tv_sec; + + /* free the oldest (unlocked) connection */ + for (i=0; iconnNotif->poolSize; i++) { + assert(ctx->connNotif->connPool[i].gss.sock > -1); // Full pool expected - accept non-NULL values only + + if (ctx->connections->connPool[i].lastUsed.tv_sec < min) { + min = ctx->connections->connPool[i].lastUsed.tv_sec; + index = i; + } + } + + ctx->connNotif->connToUse = index; + CloseConnectionNotif(ctx); + + return edg_wll_Error(ctx,NULL,NULL); +} + + int edg_wll_close(edg_wll_Context ctx, int* connToUse) { @@ -580,3 +655,138 @@ int edg_wll_http_send_recv_proxy( return edg_wll_Error(ctx,NULL,NULL); } + + +int edg_wll_accept(edg_wll_Context ctx, int fd) +{ + int recv_sock; + edg_wll_GssStatus gss_stat; + time_t lifetime = 0; + struct stat statinfo; + int acquire_cred = 0; + struct sockaddr_in a; + socklen_t alen; + edg_wll_GssStatus gss_code; + + + edg_wll_ResetError(ctx); + assert(fd > 0); + + alen=sizeof(a); + recv_sock = accept(fd,(struct sockaddr *)&a,&alen); + if (recv_sock <0) { + edg_wll_SetError(ctx, errno, "accept() failed"); + goto err; + } + + if (ctx->connNotif->connOpened == ctx->connNotif->poolSize) + if (ReleaseConnectionNotif(ctx)) goto err; + + if (SetFreeConnectionIndexNotif(ctx) < 0) { + edg_wll_SetError(ctx,EAGAIN,"connection pool size exceeded"); + goto err; + } + + #ifdef EDG_WLL_CONNPOOL_DEBUG + printf("Connection with fd %d accepted. %d in the pool\n",>srvName,ctx->srvPort,ctx->connNotif->connToUse); + #endif + + + // In case of using a specifically given cert file, stat it and check for the need to reauthenticate + if (ctx->p_proxy_filename || ctx->p_cert_filename) { + if (ctx->connNotif->connPool[ctx->connNotif->connToUse].certfile) { // Has the file been stated before? + stat(ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename, &statinfo); + if (ctx->connNotif->connPool[ctx->connNotif->connToUse].certfile->st_mtime != statinfo.st_mtime) + acquire_cred = 1; // File has been modified. Need to acquire new creds. + } + else acquire_cred = 1; + } + + // Check if credentials exist. If so, check validity + if (ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred) { + lifetime = ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred->lifetime; + #ifdef EDG_WLL_CONNPOOL_DEBUG + printf ("Credential exists, lifetime: %d\n", lifetime); + #endif + if (!lifetime) acquire_cred = 1; // Credentials exist and lifetime is OK. No need to authenticate. + } + else { + acquire_cred = 1; // No credentials exist so far, acquire. + } + + + if (acquire_cred) { + edg_wll_GssCred newcred = NULL; + if (edg_wll_gss_acquire_cred_gsi( + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename, + ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_key_filename, + &newcred, &gss_stat)) { + edg_wll_SetErrorGss(ctx, "failed to load GSI credentials", &gss_stat); + goto err; + } else { + if (ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred != NULL) + edg_wll_gss_release_cred(&ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred,&gss_stat); + ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred = newcred; + newcred = NULL; + + // Credentials Acquired successfully. Storing file identification. + #ifdef EDG_WLL_CONNPOOL_DEBUG + printf("Cert file: %s\n", ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename); + #endif + + if (ctx->p_proxy_filename || ctx->p_cert_filename) { + if (!ctx->connNotif->connPool[ctx->connNotif->connToUse].certfile) // Allocate space for certfile stats + ctx->connNotif->connPool[ctx->connNotif->connToUse].certfile = + (struct stat*)calloc(1, sizeof(struct stat)); + stat(ctx->p_proxy_filename ? ctx->p_proxy_filename : ctx->p_cert_filename, ctx->connNotif->connPool[ctx->connNotif->connToUse].certfile); + } + } + } + + assert(ctx->connNotif->connPool[ctx->connNotif->connToUse].gss.context == NULL); + + switch ( edg_wll_gss_accept(ctx->connNotif->connPool[ctx->connNotif->connToUse].gsiCred, recv_sock, + &ctx->p_tmp_timeout, &ctx->connNotif->connPool[ctx->connNotif->connToUse].gss,&gss_code)) { + + case EDG_WLL_GSS_OK: + break; + case EDG_WLL_GSS_ERROR_ERRNO: + edg_wll_SetError(ctx,errno,"failed to receive notification"); + goto err; + case EDG_WLL_GSS_ERROR_GSS: + edg_wll_SetErrorGss(ctx, "failed to authenticate sender", &gss_code); + goto err; + case EDG_WLL_GSS_ERROR_HERRNO: + { const char *msg1; + char *msg2; + msg1 = hstrerror(errno); + asprintf(&msg2, "edg_wll_gss_connect(): %s", msg1); + edg_wll_SetError(ctx,EDG_WLL_ERROR_DNS, msg2); + free(msg2); + } + break; + case EDG_WLL_GSS_ERROR_EOF: + edg_wll_SetError(ctx,ECONNREFUSED,"sender closed the connection"); + goto err; + case EDG_WLL_GSS_ERROR_TIMEOUT: + edg_wll_SetError(ctx,ETIMEDOUT,"accepting notification"); + goto err; + default: + edg_wll_SetError(ctx, ENOTCONN, "failed to accept notification"); + goto err; + } + + return edg_wll_Error(ctx,NULL,NULL); + + +err: + /* some error occured; close created connection + * and free all fields in connPool[ctx->connNotif->connToUse] */ + if (ctx->connNotif->connToUse >= 0) { + CloseConnectionNotif(ctx); + } + + + return edg_wll_Error(ctx,NULL,NULL); +} + -- 1.8.2.3