-lglobus_common_${nothrflavour} \
-lglobus_gssapi_gsi_${nothrflavour}
+GLOBUS_CFLAGS:=-I${globus_prefix}/include/${nothrflavour}
+
DEBUG:=-g -O0 -DDEBUG
-CFLAGS:=${DEBUG} -I. -I${top_srcdir}/src -I${gsoap_prefix}/include -I${stagedir}/include
+CFLAGS:=${DEBUG} -I. -I${top_srcdir}/src -I${gsoap_prefix}/include -I${stagedir}/include ${GLOBUS_CFLAGS}
LDFLAGS:=-L${stagedir}/lib
LINK:=libtool --mode=link ${CC} ${LDFLAGS}
CFLAGS+=-DGSOAP_VERSION=${gsoap_version}
-SRCS:= simple_server.c soap_ops.c \
+SRCS:= bones_server.c soap_ops.c \
ftp_backend.c \
feed.c tags.c\
is_client.c \
EXA_OBJS:=${EXA_SRCS:.c=.o}
COMMONLIB:=-lglite_jp_common
-GSOAPLIB:=-L${gsoap_prefix}/lib -lgsoap${GSOAP_DEBUG}
+BONESLIB:=-lglite_lb_server_bones
+GSOAPLIB:=-lglite_security_gsoap_plugin_${nothrflavour} -lglite_security_gss_${nothrflavour} \
+ -L${gsoap_prefix}/lib -lgsoap${GSOAP_DEBUG} -L${ares_prefix}/lib -lares
default all: compile
compile: ${daemon} ${example}
${daemon}: ${OBJS}
- ${LINK} -o $@ ${OBJS} ${COMMONLIB} ${GSOAPLIB} ${GLOBUS_LIBS}
+ ${LINK} -o $@ ${OBJS} ${BONESLIB} ${COMMONLIB} ${GSOAPLIB} ${GLOBUS_LIBS}
${example}: ${EXA_OBJS}
- ${LINK} -o $@ ${EXA_OBJS} ${GSOAPLIB}
+ ${LINK} -o $@ ${EXA_OBJS} ${GSOAPLIB} ${GLOBUS_LIBS}
JobProvenanceIS.xh JobProvenancePS.xh: %.xh: %.wsdl JobProvenanceTypes.wsdl typemap.dat
cp ${stagedir}/interface/JobProvenanceTypes.wsdl .
#
-simple_server.o: ${is_prefix}H.h ${ps_prefix}H.h
+bones_server.o simple_server.o: ${is_prefix}H.h ${ps_prefix}H.h
check:
-echo nothing yet
#include <string.h>
#include <assert.h>
+#include "glite/security/glite_gsplugin.h"
+
#include "jpps_H.h"
#include "jpps_.nsmap"
fprintf(stderr,"%s: [-s server-url] operation args \n\n"
" operations are:\n"
" RegisterJob jobid\n"
- " StartUpload jobid class(0,1,2) commit_before mimetype\n"
+ " StartUpload jobid class commit_before mimetype\n"
" CommitUpload destination\n"
" RecordTag jobid tagname sequence stringvalue\n"
" GetJob jobid\n"
soap_init(soap);
soap_set_namespaces(soap, jpps__namespaces);
+ soap_register_plugin(soap,glite_gsplugin);
+
while ((opt = getopt(argc,argv,"s:")) >= 0) switch (opt) {
case 's': server = optarg;
argv += 2;
if (argc != 6) usage(argv[0]);
if (!check_fault(soap,
soap_call_jpsrv__StartUpload(soap, server, "",
- argv[2], atoi(argv[3]), atoi(argv[4]), argv[5], &r))) {
+ argv[2], argv[3], "", atoi(argv[4]), argv[5], &r))) {
printf("Destination: %s\nCommit before: %s\n", r.destination, ctime(&r.commitBefore));
}
} else if (!strcasecmp(argv[1], "CommitUpload")) {
--- /dev/null
+#ifndef __GLITE_JP_FILEPLUGIN
+#define __GLITE_JP_FILEPLUGIN
+
+/** Methods of the file plugin. */
+
+typedef struct _glite_jp_fplug_op_t {
+
+/** Open a file.
+\param[in] fpctx Context of the plugin, returned by its init.
+\param[in] bhandle Handle of the file via JPPS backend.
+\param[out] handle Handle to the opened file structure, to be passed to other plugin functions.
+*/
+ int (*open)(void *fpctx,void *bhandle,void **handle);
+
+/** Close the file. Free data associated to a handle */
+ int (*close)(void *fpctx,void *handle);
+
+/** Retrieve value(s) of an attribute.
+\param[in] fpctx Plugin context.
+\param[in] handle Handle of the opened file.
+\param[in] attr Queried attribute.
+\param[out] attrval GLITE_JP_ATTR_UNDEF-terminated list of value(s) of the attribute.
+ If there are more and there is an interpretation of their order
+ they must be sorted, eg. current value of tag is the last one.
+\retval 0 success
+\retval ENOSYS this attribute is not defined by this type of file
+\retval ENOENT no value is present
+*/
+ int (*attr)(void *fpctx,void *handle,glite_jp_attr_t attr,glite_jp_attrval_t **attrval);
+
+/** File type specific operation.
+\param[in] fpctx Plugin context.
+\param[in] handle Handle of the opened file.
+\param[in] oper Code of the operation, specific for a concrete plugin.
+*/
+ int (*op)(void *fpctx,void *handle,int oper,...);
+
+} glite_jp_fplug_op_t;
+
+/** Initialisation function of the plugin.
+ Called after dlopen(), must be named "init".
+\param[in] ctx JPPS context
+\param[out] uris NULL-terminated list of file types (URIs) handled by the plugin
+\param[out] ops Plugin methods.
+\param[out] fpctx Initialised plugin context, to be passed to the methods.
+*/
+
+typedef int (*glite_jp_fplug_init_t)(glite_jp_context_t ctx,char ***uris,glite_jp_fplug_op_t *ops,void **fpctx);
+
+
+#endif
int glite_jppsbe_start_upload(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class, /* must be filesystem-friendly */
+ const char *name, /* optional name within the class */
const char *content_type,
char **destination_out,
time_t *commit_before_inout
glite_jp_context_t ctx,
const char *destination,
char **job_out,
- glite_jp_fileclass_t *class_out
+ char **class_out
);
int glite_jppsbe_get_job_url(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* optional within class */
char **url_out
);
int glite_jppsbe_open_file(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* optional within class */
int mode,
void **handle_out
);
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "glite/jp/types.h"
+#include "glite/jp/context.h"
+
+#include "glite/lb/srvbones.h"
+#include "glite/security/glite_gss.h"
+
+#include <stdsoap2.h>
+#include "glite/security/glite_gsplugin.h"
+
+
+
+#include "jpps_H.h"
+
+#define CONN_QUEUE 20
+
+extern SOAP_NMAC struct Namespace jpis__namespaces[],jpps__namespaces[];
+
+static int newconn(int,struct timeval *,void *);
+static int request(int,struct timeval *,void *);
+static int reject(int);
+static int disconn(int,struct timeval *,void *);
+static int data_init(void **data);
+
+static struct glite_srvbones_service stab = {
+ "JP Primary Storage", -1, newconn, request, reject, disconn
+};
+
+static time_t cert_mtime;
+static char *server_cert, *server_key, *cadir;
+static gss_cred_id_t mycred = GSS_C_NO_CREDENTIAL;
+static char *mysubj;
+
+static char *port = "8901";
+static int debug = 1;
+
+static glite_jp_context_t ctx;
+
+int main(int argc, char *argv[])
+{
+ int one = 1;
+ edg_wll_GssStatus gss_code;
+ struct sockaddr_in a;
+
+ /* XXX: read options */
+
+ glite_jp_init_context(&ctx);
+
+ if (glite_jppsbe_init(ctx, &argc, argv)) {
+ /* XXX log */
+ fputs(glite_jp_error_chain(ctx), stderr);
+ exit(1);
+ }
+
+ srand48(time(NULL)); /* feed id generation */
+
+ stab.conn = socket(PF_INET, SOCK_STREAM, 0);
+ if (stab.conn < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ setsockopt(stab.conn,SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+
+ a.sin_family = AF_INET;
+ a.sin_addr.s_addr = INADDR_ANY;
+ a.sin_port = htons(atoi(port));
+ if (bind(stab.conn,(struct sockaddr *) &a, sizeof(a)) ) {
+ char buf[200];
+
+ snprintf(buf,sizeof(buf),"bind(%d)",atoi(port));
+ perror(buf);
+ return 1;
+ }
+
+ if (listen(stab.conn,CONN_QUEUE)) {
+ perror("listen()");
+ return 1;
+ }
+
+ if (!server_cert || !server_key)
+ fprintf(stderr, "%s: WARNING: key or certificate file not specified,"
+ "can't watch them for changes\n",
+ argv[0]);
+
+ if ( cadir ) setenv("X509_CERT_DIR", cadir, 1);
+ edg_wll_gss_watch_creds(server_cert, &cert_mtime);
+
+ if ( !edg_wll_gss_acquire_cred_gsi(server_cert, server_key, &mycred, &mysubj, &gss_code))
+ fprintf(stderr,"Server idenity: %s\n",mysubj);
+ else fputs("WARNING: Running unauthenticated\n",stderr);
+
+ /* XXX: daemonise */
+
+ glite_srvbones_set_param(GLITE_SBPARAM_SLAVES_COUNT,1);
+ glite_srvbones_run(data_init,&stab,1 /* XXX: entries in stab */,debug);
+
+ return 0;
+}
+
+static int data_init(void **data)
+{
+ *data = (void *) soap_new();
+
+ printf("[%d] slave started\n",getpid());
+
+ return 0;
+}
+
+static int newconn(int conn,struct timeval *to,void *data)
+{
+ struct soap *soap = (struct soap *) data;
+ glite_gsplugin_Context plugin_ctx;
+
+ gss_cred_id_t newcred = GSS_C_NO_CREDENTIAL;
+ edg_wll_GssStatus gss_code;
+ gss_name_t client_name = GSS_C_NO_NAME;
+ gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+ OM_uint32 maj_stat,min_stat;
+
+
+ int ret = 0;
+
+ soap_init2(soap,SOAP_IO_KEEPALIVE,SOAP_IO_KEEPALIVE);
+ soap_set_namespaces(soap,jpps__namespaces);
+ soap->user = (void *) ctx; /* XXX: one instance per slave */
+
+/* not yet: client to JP index
+ ctx->other_soap = soap_new();
+ soap_init(ctx->other_soap);
+ soap_set_namespaces(ctx->other_soap,jpis__namespaces);
+*/
+
+
+ glite_gsplugin_init_context(&plugin_ctx);
+ plugin_ctx->connection = calloc(1,sizeof *plugin_ctx->connection);
+ soap_register_plugin_arg(soap,glite_gsplugin,plugin_ctx);
+
+ switch (edg_wll_gss_watch_creds(server_cert,&cert_mtime)) {
+ case 0: break;
+ case 1: if (!edg_wll_gss_acquire_cred_gsi(server_cert,server_key,
+ &newcred,NULL,&gss_code))
+ {
+
+ printf("[%d] reloading credentials\n",getpid()); /* XXX: log */
+ gss_release_cred(&min_stat,&mycred);
+ mycred = newcred;
+ }
+ break;
+ case -1:
+ printf("[%d] edg_wll_gss_watch_creds failed\n", getpid()); /* XXX: log */
+ break;
+ }
+
+ /* TODO: DNS paranoia etc. */
+
+ if (edg_wll_gss_accept(mycred,conn,to,plugin_ctx->connection,&gss_code)) {
+ printf("[%d] GSS connection accept failed, closing.\n", getpid());
+ ret = 1;
+ goto cleanup;
+ }
+
+ maj_stat = gss_inquire_context(&min_stat,plugin_ctx->connection->context,
+ &client_name, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (!GSS_ERROR(maj_stat))
+ maj_stat = gss_display_name(&min_stat,client_name,&token,NULL);
+
+ if (ctx->peer) free(ctx->peer);
+ if (!GSS_ERROR(maj_stat)) {
+ printf("[%d] client DN: %s\n",getpid(),(char *) token.value); /* XXX: log */
+
+ ctx->peer = strdup(token.value);
+ memset(&token, 0, sizeof(token));
+ }
+ else {
+ printf("[%d] annonymous client\n",getpid());
+ ctx->peer = NULL;
+ }
+
+ if (client_name != GSS_C_NO_NAME) gss_release_name(&min_stat, &client_name);
+ if (token.value) gss_release_buffer(&min_stat, &token);
+
+ return 0;
+
+cleanup:
+ glite_gsplugin_free_context(plugin_ctx);
+ soap_end(soap);
+
+ return ret;
+}
+
+static int request(int conn,struct timeval *to,void *data)
+{
+ struct soap *soap = data;
+ glite_jp_context_t ctx = soap->user;
+
+ glite_gsplugin_set_timeout(glite_gsplugin_get_context(soap),to);
+
+/* FIXME: does not work, ask nykolas */
+ soap->max_keep_alive = 1; /* XXX: prevent gsoap to close connection */
+ soap_begin(soap);
+ if (soap_begin_recv(soap)) {
+ if (soap->error < SOAP_STOP) {
+ soap_send_fault(soap);
+ return -1;
+ }
+ return ENOTCONN;
+ }
+
+ if (soap_envelope_begin_in(soap)
+ || soap_recv_header(soap)
+ || soap_body_begin_in(soap)
+ || jpps__serve_request(soap)
+#if GSOAP_VERSION >= 20700
+ || (soap->fserveloop && soap->fserveloop(soap))
+#endif
+ )
+ {
+ soap_send_fault(soap);
+ return -1;
+ }
+
+ glite_jp_run_deferred(ctx);
+}
+
+static int reject(int conn)
+{
+ int flags = fcntl(conn, F_GETFL, 0);
+
+ fcntl(conn,F_SETFL,flags | O_NONBLOCK);
+ edg_wll_gss_reject(conn);
+
+ return 0;
+}
+
+static int disconn(int conn,struct timeval *to,void *data)
+{
+ struct soap *soap = (struct soap *) data;
+ soap_end(soap); // clean up everything and close socket
+
+ return 0;
+}
+
+
+/* XXX: we don't use it */
+SOAP_NMAC struct Namespace namespaces[] = { {NULL,NULL} };
{ NULL, 0, NULL, 0 }
};
+/* obsolete */
+#if 0
static struct {
glite_jp_fileclass_t type;
char * fname;
return GLITE_JP_FILECLASS_UNDEF;
}
+#endif
static int config_check(
glite_jp_context_t ctx,
int glite_jppsbe_start_upload(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* TODO */
const char *content_type,
char **destination_out,
time_t *commit_before_inout
char *lock_fname = NULL;
FILE *lockfile = NULL;
FILE *regfile = NULL;
- char *fname = NULL;
char *data_dir = NULL;
char *data_lock = NULL;
char *ju = NULL;
assert(job!=NULL);
assert(destination_out!=NULL);
- fname = class_to_fname(class);
- assert(fname!=NULL);
+ assert(class!=NULL);
if (jobid_unique_pathname(ctx, job, &ju, &ju_path, 1) != 0) {
err.code = ctx->error->code;
}
if (asprintf(&lock_fname, "%s/%s" LOCK_SUFFIX,
- data_dir, fname) == -1) {
+ data_dir, class) == -1) {
err.code = ENOMEM;
goto error_out;
}
}
if (asprintf(destination_out, "%s/data/%s/%d/%s/%s" UPLOAD_SUFFIX,
- config->external_path, ownerhash, regtime_trunc(reg_time), ju, fname) == -1) {
+ config->external_path, ownerhash, regtime_trunc(reg_time), ju, class) == -1) {
err.code = ENOMEM;
goto error_out;
}
glite_jp_context_t ctx,
const char *destination,
char **job,
- glite_jp_fileclass_t *class
+ char **class
)
{
size_t dest_len;
goto error_out;
}
*classname++ ='\0';
- *class = fname_to_class(classname);
+ *class = strdup(classname);
+
+/* XXX: do we need similar check?
if (!class == GLITE_JP_FILECLASS_UNDEF) {
err.code = EINVAL;
err.desc = "Forged destination path";
goto error_out;
}
+*/
if (asprintf(&dest_rw_info, "%s/_info", dest_rw) == -1) {
err.code = ENOMEM;
int glite_jppsbe_get_job_url(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* TODO */
char **url_out
)
{
FILE *regfile = NULL;
char *int_fname = NULL;
- char *fname = NULL;
char *ju = NULL;
char *ju_path = NULL;
int info_version;
err.source = __FUNCTION__;
assert(job!=NULL);
- assert(class != GLITE_JP_FILECLASS_UNDEF);
assert(url_out != NULL);
- fname = class_to_fname(class);
- assert(fname!=NULL);
+ assert(class!=NULL);
if (jobid_unique_pathname(ctx, job, &ju, &ju_path, 1) != 0) {
err.code = ctx->error->code;
fclose(regfile);
if (asprintf(url_out, "%s/data/%s/%d/%s/%s",
- config->external_path, ownerhash, regtime_trunc(reg_time), ju, fname) == -1) {
+ config->external_path, ownerhash, regtime_trunc(reg_time), ju, class) == -1) {
err.code = ENOMEM;
goto error_out;
}
static int get_job_fname(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* TODO */
char **fname_out
)
{
FILE *regfile = NULL;
- char *fname = NULL;
char *int_fname = NULL;
char *ju = NULL;
char *ju_path = NULL;
err.source = __FUNCTION__;
assert(job!=NULL);
- assert(class != GLITE_JP_FILECLASS_UNDEF);
assert(fname_out != NULL);
- fname = class_to_fname(class);
- assert(fname!=NULL);
+ assert(class!=NULL);
if (jobid_unique_pathname(ctx, job, &ju, &ju_path, 1) != 0) {
err.code = ctx->error->code;
fclose(regfile);
if (asprintf(fname_out, "%s/data/%s/%d/%s/%s",
- config->internal_path, ownerhash, regtime_trunc(reg_time), ju, fname) == -1) {
+ config->internal_path, ownerhash, regtime_trunc(reg_time), ju, class) == -1) {
err.code = ENOMEM;
goto error_out;
}
int glite_jppsbe_open_file(
glite_jp_context_t ctx,
const char *job,
- glite_jp_fileclass_t class,
+ const char *class,
+ const char *name, /* TODO */
int mode,
void **handle_out
)
memset(&err,0,sizeof err);
err.source = __FUNCTION__;
- if (get_job_fname(ctx, job, class, &fname)) {
+ if (get_job_fname(ctx, job, class, name, &fname)) {
err.code = ctx->error->code;
err.desc = "Cannot construct internal filename";
return glite_jp_stack_error(ctx,&err);
for (i = 0; attrs_inout[i].attr.type != GLITE_JP_ATTR_UNDEF; i++) {
switch (attrs_inout[i].attr.type) {
case GLITE_JP_ATTR_OWNER:
+
+/* must be implemented via filetype plugin
case GLITE_JP_ATTR_TIME:
+*/
if (!got_info) {
if (get_job_info(ctx, job, &owner, &tv_reg)) {
err.code = ctx->error->code;
got_info = 1;
}
break;
+
+/* must be implemented via filetype plugin
case GLITE_JP_ATTR_TAG:
if (!got_tags) {
if (glite_jppsbe_open_file(ctx, job, GLITE_JP_FILECLASS_TAGS,
got_tags = 1;
}
break;
+*/
default:
err.code = EINVAL;
err.desc = "Invalid attribute type";
case GLITE_JP_ATTR_TIME:
attrs_inout[i].value.time = tv_reg;
break;
+
+/* must be implemented via filetype plugin
case GLITE_JP_ATTR_TAG:
for (j = 0; tags[j].name != NULL; j++) {
if (!strcmp(tags[j].name, attrs_inout[i].attr.name)) {
}
if (!tags[j].name) attrs_inout[i].value.tag.name = NULL;
break;
+*/
default:
break;
}
return 0;
}
+
+/* FIXME: disabled -- clarification wrt. filetype plugin needed */
+
+#if 0
+
static int query_phase2(
glite_jp_context_t ctx,
const char *ownerhash,
return glite_jp_stack_error(ctx,&err);
}
+#else
+
+/* placeholder instead */
+int glite_jppsbe_query(
+ glite_jp_context_t ctx,
+ const glite_jp_query_rec_t query[],
+ const glite_jp_attrval_t metadata[],
+ int (*callback)(
+ glite_jp_context_t ctx,
+ const char *job,
+ const glite_jp_attrval_t metadata[]
+ )
+)
+{
+ glite_jp_error_t err;
+ err.code = ENOSYS;
+ err.desc = "not implemented";
+ return glite_jp_stack_error(ctx,&err);
+}
+
+#endif
+
/* XXX:
- no primary authorization yet
- no concurrency control yet
else soap->fault->detail = detail;
}
+/* deprecated
static glite_jp_fileclass_t s2jp_fileclass(enum jptype__UploadClass class)
{
switch (class) {
default: return GLITE_JP_FILECLASS_UNDEF;
}
}
+*/
static void s2jp_tag(const struct jptype__TagValue *stag,glite_jp_tagval_t *jptag)
{
SOAP_FMAC5 int SOAP_FMAC6 jpsrv__StartUpload(
struct soap *soap,
char *job,
- enum jptype__UploadClass class,
+ char *class,
+ char *name,
time_t commit_before,
char *content_type,
struct jpsrv__StartUploadResponse *response)
{
CONTEXT_FROM_SOAP(soap,ctx);
- glite_jp_fileclass_t jclass = s2jp_fileclass(class);
char *destination;
- if (glite_jppsbe_start_upload(ctx,job,jclass,content_type,&destination,&commit_before)) {
+ if (glite_jppsbe_start_upload(ctx,job,class,name,content_type,&destination,&commit_before)) {
err2fault(ctx,soap);
return SOAP_FAULT;
}