./0040755000000000000000000000000007635636256007737 5ustar rootroot./Makefile0100666002342100000120000000051407635617204010624 0ustar wheel # VERSION=0.2 OBEX_VER=1.0.0 CC = gcc LDFLAGS = CFLAGS = -I. all : \ opd BIPD_OBJECTS = \ main.o \ lib.o \ obex_handler.o opd : $(BIPD_OBJECTS) $(CC) -o opd $(CFLAGS) $(BIPD_OBJECTS) -lopenobex -lbluetooth -lsdp $(LDFLAGS) clean: -@rm *.o tar: -@tar czf opd-v$(VERSION)-`date +%Y-%m-%d`.tgz . -X donttar ./lib.c0100666000000000000000000000557707631370407010655 0ustar rootroot/* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated Written 2000,2001 by Maxim Krasnyansky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. */ /* * $Id: lib.c,v 1.2 2002/06/24 02:38:01 maxk Exp $ */ #include #include #include #include #include #include #include #include "lib.h" volatile sig_atomic_t __io_canceled; /* Returns current host name */ char *get_host_name(void) { char name[40]; if (!gethostname(name, sizeof(name)-1)) { name[sizeof(name)-1] = 0; return strdup(name); } return strdup("noname"); } /* Functions to manipulate program title */ extern char **environ; char *title_start; /* start of the proc title space */ char *title_end; /* end of the proc title space */ int title_size; void init_title(int argc, char *argv[], char *envp[], const char *name) { int i; /* * Move the environment so settitle can use the space at * the top of memory. */ for (i = 0; envp[i]; i++); environ = (char **) malloc(sizeof (char *) * (i + 1)); for (i = 0; envp[i]; i++) environ[i] = strdup(envp[i]); environ[i] = NULL; /* * Save start and extent of argv for set_title. */ title_start = argv[0]; /* * Determine how much space we can use for set_title. * Use all contiguous argv and envp pointers starting at argv[0] */ for (i=0; i title_size - 1) buf[title_size - 1] = '\0'; strcat(title_start, buf); } ./lib.h0100666000000000000000000000426107631370442010646 0ustar rootroot/* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated Written 2000,2001 by Maxim Krasnyansky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. */ /* * $Id: lib.h,v 1.2 2002/06/24 02:38:01 maxk Exp $ */ #include char *get_host_name(void); void init_title(int argc, char *argv[], char *env[], const char *name); void set_title(const char *ftm, ...); /* IO cancelation */ extern volatile sig_atomic_t __io_canceled; static inline void io_init(void) { __io_canceled = 0; } static inline void io_cancel(void) { __io_canceled = 1; } /* Read exactly len bytes (Signal safe)*/ static inline int read_n(int fd, void *buf, int len) { register int t = 0, w; while (!__io_canceled && len > 0) { if ((w = read(fd, buf, len)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; return -1; } if (!w) return 0; len -= w; buf += w; t += w; } return t; } /* Write exactly len bytes (Signal safe)*/ static inline int write_n(int fd, void *buf, int len) { register int t = 0, w; while (!__io_canceled && len > 0) { if ((w = write(fd, buf, len)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; return -1; } if (!w) return 0; len -= w; buf += w; t += w; } return t; } ./donttar0100666000000000000000000000004307635623020011314 0ustar rootroot*.txt opd *.tgz *.o junk x-bt dest ./obex_handler.c0100666002342100000120000003041507635636250011767 0ustar wheel/* CPRY: (C)2003 Beier & Dauskardt IT (www.bdit.de) FILE: obex_handler.c AUTH: Sancho Dauskardt DATE: 05.03.2003 CMNT: opd OBEX Event processing. */ /* * * * Parts by: Pontus Fuchs * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "obex_handler.h" #include "main.h" #define TRUE 1 #define FALSE 0 int srv_BIPNextImageHandle=1; // Answer for BIP GetCapabilities(): 'x-bt/img-capabilities' // const char *bt_img_capabilities = "\n" " \n" "\n" ; /* Get the filesize in a "portable" way */ int get_filesize(const char *filename) { struct stat stats; /* Need to know the file length */ stat(filename, &stats); return (int) stats.st_size; } /* ** Read a file and alloc a buffer for it */ uint8_t* easy_readfile(const char *filename, int *file_size) { int actual; int fd; uint8_t *buf; *file_size = get_filesize(filename); printf("name=%s, size=%d\n", filename, *file_size); fd = open(filename, O_RDONLY, 0); if (fd == -1) { return NULL; } buf = (uint8_t *)malloc(*file_size); if(!buf){ return NULL; } actual = read(fd, buf, *file_size); close(fd); *file_size = actual; return buf; } /* * * * First remove path and add "/tmp/". Then save. * */ int save_binary_file(char *filename, const uint8_t *buf, int len) { int fd; int actual; printf("Filename = %s\n", filename); fd = open(filename, O_RDWR | O_CREAT, DEFFILEMODE); if ( fd < 0) { perror( filename); return -1; } actual = write(fd, buf, len); close(fd); printf( "Wrote %s (%d bytes)\n", filename, actual); return actual; } // // void dump_hex(void *dataptr,int length) { int i; char ascii[17]; int asciiofs=0; unsigned char *data = (unsigned char *)dataptr; for(i=0;i= 0x20 ){ ascii[asciiofs++] = data[i]; }else{ ascii[asciiofs++] = '.'; } if(i % 16 == 15){ ascii[asciiofs] =0; printf(" %s\n",ascii); asciiofs=0; } } if(i % 16 != 0){ for(;(i%16!=0);i++){ printf(" "); ascii[asciiofs++] = ' '; } ascii[asciiofs] =0; printf(" %s\n",ascii); } } // Get the Bluetooth bdaddr to an OBEX-handle. // int Get_handle_bdaddr(obex_t *handle,char *str) { int fd; struct sockaddr_rc sa; socklen_t len = sizeof(sa); fd = OBEX_GetFD(handle); if( fd < 0 ) return 0; if( getpeername(fd,(struct sockaddr *)&sa,&len) < 0 ) return 0; if( sa.rc_family != AF_BLUETOOTH ) return 0; ba2str(&sa.rc_bdaddr,str); return 1; } int Get_handle_irdaaddr(obex_t *handle,char *str) { int fd; struct sockaddr_irda sa; socklen_t len = sizeof(sa); fd = OBEX_GetFD(handle); if( fd < 0 ) return 0; if( getpeername(fd,(struct sockaddr *)&sa,&len) < 0 ) return 0; if( sa.sir_family != AF_IRDA ) return 0; sprintf(str,"%02x-%08x-%s", sa.sir_lsap_sel, /* LSAP selector */ sa.sir_addr, /* Device address */ sa.sir_name /* Usually :IrDA:TinyTP */ ); return 1; } // For log-messages. // int GetOBEXPeerName(obex_t *handle,char *str) { switch( OPD_SocketType() ){ case AF_BLUETOOTH: if( Get_handle_bdaddr(handle,str) ) return 1; strcpy(str,"unknown-br"); break; case AF_IRDA: if( Get_handle_irdaaddr(handle,str) ) return 1; strcpy(str,"unknown-irda"); break; default: strcpy(str,"unknown-af"); break; } return 0; } /* void Handle_OBEX_CMD_PUT(obex_t *handle, obex_object_t *object) * * * * Parse what we got from a PUT * */ void Handle_OBEX_CMD_PUT(obex_t *handle, obex_object_t *object) { obex_headerdata_t hv; uint8_t hi; int hlen; const uint8_t *body = NULL; int body_len = 0; const uint8_t *headertype = NULL; int headertype_len = 0; const uint8_t *imgdesc = NULL; int imgdesc_len = 0; int GotName=0; char NameBuf[1024]; char *LastSlash; char SafeName[1024]; int fd; while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { switch(hi) { case OBEX_HDR_BODY: body = hv.bs; body_len = hlen; break; case OBEX_HDR_NAME: if( hlen/2 < sizeof(NameBuf) ){ OBEX_UnicodeToChar(NameBuf, hv.bs, hlen); GotName = TRUE; } break; case OBEX_HDR_LENGTH: printf("HEADER_LENGTH = %d\n", hv.bq4); break; case OBEX_HDR_TYPE: printf("HEADER_TYPE = '%s' #%d \n", hv.bs, hlen); dump_hex((void *)hv.bs,hlen); headertype = hv.bs; headertype_len = hlen; break; case 0xcb: printf("CONNECTION_ID = %#x (%d length)\n", hv.bq4,hlen); break; case 0x71: printf("IMAGE_DESCRIPTION = ? (%d length)\n",hlen); dump_hex((void *)hv.bs,hlen); imgdesc = hv.bs; imgdesc_len = hlen; break; default: printf(__FUNCTION__ "() Skipped header %02x\n", hi); } } if(!body){ printf("Got a PUT without a body\n"); OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); return; } if(!GotName){ sprintf(NameBuf,"OBEX_PUT_Unknown_object_%07d",srv_BIPNextImageHandle); GotName = TRUE; printf("Got a PUT without a name. Setting name to %s\n", NameBuf); } // Remove possible path from target name und // use our path. // strcpy(SafeName,srv_BasePath); if( (LastSlash = strrchr(NameBuf,'/')) ){ LastSlash++; }else{ if( (LastSlash = strrchr(NameBuf,'\\')) ){ LastSlash++; }else{ LastSlash = NameBuf; } } strcat(SafeName,LastSlash); if( srv_Metadata && (OPD_SocketType()==AF_BLUETOOTH) ){ char bdaddr_str[256]; if( headertype ){ char DumpName[2048]; sprintf(DumpName,"%s.bt-headertype",SafeName); save_binary_file(DumpName, headertype, headertype_len); } if( imgdesc ){ char DumpName[2048]; sprintf(DumpName,"%s.bt-imagedesc",SafeName); save_binary_file(DumpName, imgdesc, imgdesc_len); } if( Get_handle_bdaddr(handle,bdaddr_str)){ char DumpName[2048]; sprintf(DumpName,"%s.bt-addr",SafeName); save_binary_file(DumpName, bdaddr_str, strlen(bdaddr_str)); } } // Save the actual file last. // save_binary_file(SafeName, body, body_len); // In BIP-Mode we need to answer with a Image-Handle // if( srv_Modes & OPDM_BIP ){ char ImageHandle[64]; OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); // Generate next Image-Handle. // sprintf(ImageHandle,"%07d",srv_BIPNextImageHandle++); hv.bs = ImageHandle; OBEX_ObjectAddHeader( handle, object, 0x30, // Img-Handle hv, strlen(ImageHandle)+1, // Length 0 ); }else{ OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); } } /* void Handle_OBEX_CMD_GET(obex_t *handle, obex_object_t *object) ** ** ** ** Handles a OBEX GET command. ** ** ** BIP Mode: ** - Answer GetCapabilities() request. ** ** Non BIP: ** - Answer NOT_FOUND to all. ** */ void Handle_OBEX_CMD_GET(obex_t *handle, obex_object_t *object) { obex_headerdata_t hv; uint8_t hi; int hlen; int GotName=0; char NameBuf[1024]; int GotType=0; char TypeBuf[1024]; printf(__FUNCTION__ "()\n"); while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)){ switch(hi) { case OBEX_HDR_NAME: printf(__FUNCTION__ "() Found name\n"); if( hlen/2 < sizeof(NameBuf) ){ OBEX_UnicodeToChar(NameBuf, hv.bs, hlen); GotName = TRUE; } break; case OBEX_HDR_TYPE: printf(__FUNCTION__ "() HEADER_TYPE = '%s' #%d \n", hv.bs, hlen); if( hlen < sizeof(TypeBuf) ){ strcpy(TypeBuf,hv.bs); GotType = TRUE; } break; case 0xcb: printf(__FUNCTION__ "()CONNECTION_ID = %#x (%d length)\n", hv.bq4,hlen); break; case 0x71: printf(__FUNCTION__ "()IMAGE_DESCRIPTION = ? (%d length)\n",hlen); dump_hex((void *)hv.bs,hlen); break; default: printf(__FUNCTION__ "() Skipped header %02x\n", hi); } } // // if( (srv_Modes & OPDM_BIP) && GotType && !strcmp(TypeBuf,"x-bt/img-capabilities") ){ OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); hv.bs = bt_img_capabilities; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, strlen(bt_img_capabilities), 0); hv.bq4 = strlen(bt_img_capabilities); OBEX_ObjectAddHeader(handle, object, OBEX_HDR_LENGTH, hv, sizeof(uint32_t), 0); return; } // We won'tanswer any other get's. // if(GotName){ printf(__FUNCTION__ "() Got a request for %s\n", NameBuf); }else{ printf(__FUNCTION__ "() Got a GET without a name-header!\n"); } OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_FOUND, OBEX_RSP_NOT_FOUND); return; } /* void Handle_ServerRequest(obex_t *handle, obex_object_t *object, int event, int cmd) * * * Called when a request is about to come or has come. * */ void Handle_ServerRequest(obex_t *handle, obex_object_t *object, int event, int cmd) { char peeraddr_str[256]; switch(cmd) { case OBEX_CMD_SETPATH: printf("Received SETPATH command\n"); OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; case OBEX_CMD_PUT: Handle_OBEX_CMD_PUT(handle,object); break; case OBEX_CMD_GET: Handle_OBEX_CMD_GET(handle,object); break; case OBEX_CMD_CONNECT: GetOBEXPeerName(handle,peeraddr_str); syslog(LOG_INFO, "OBEX connect from %s",peeraddr_str); OBEX_ObjectSetRsp(object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); break; case OBEX_CMD_DISCONNECT: GetOBEXPeerName(handle,peeraddr_str); syslog(LOG_INFO, "OBEX disconnect from %s",peeraddr_str); OBEX_ObjectSetRsp(object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); break; default: printf(__FUNCTION__ "() Denied %02x request\n", cmd); OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; } return; } char *event_name(int event) { switch (event) { case OBEX_EV_PROGRESS: return "EV_PROGRESS"; case OBEX_EV_REQDONE: return "EV_REQDONE"; case OBEX_EV_REQHINT: return "EV_REQHINT"; case OBEX_EV_REQ: return "EV_REQ"; case OBEX_EV_LINKERR: return "EV_LINKERR"; default: return "EV_UNKNOWN"; } } char *cmd_name(int cmd) { switch(cmd) { case OBEX_CMD_SETPATH: return "CMD_SETPATH"; case OBEX_CMD_PUT: return "CMD_PUT"; case OBEX_CMD_GET: return "CMD_GET"; case OBEX_CMD_CONNECT: return "CMD_CONNECT"; case OBEX_CMD_DISCONNECT: return "CMD_DISCONNECT"; default: return "CMD_??????"; } return; } /* * Handle_OBEX_Event() * * Called by the obex-layer when some event occurs. * */ void Handle_OBEX_Event(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { char peeraddr_str[256]; printf("\n obex_event: %d %d(%11s) %d(%14s) %d\n", mode, event, event_name(event), obex_cmd, cmd_name(obex_cmd), obex_rsp ); // switch( event ){ case OBEX_EV_PROGRESS: break; case OBEX_EV_REQDONE: break; case OBEX_EV_REQHINT: switch(obex_cmd) { case OBEX_CMD_PUT: case OBEX_CMD_CONNECT: case OBEX_CMD_DISCONNECT: OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; default: OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; } break; case OBEX_EV_REQ: Handle_ServerRequest(handle, object, event, obex_cmd); break; case OBEX_EV_LINKERR: GetOBEXPeerName(handle,peeraddr_str); syslog(LOG_INFO, "lost link to %s",peeraddr_str); OBEX_TransportDisconnect(handle); break; default: printf("Unknown event %d !\n",event); break; } } ./obex_handler.h0100666002342100000120000000212607635622770011774 0ustar wheel/* CPRY: (C)2003 Beier & Dauskardt IT (www.bdit.de) FILE: obex_handler.c AUTH: Sancho Dauskardt DATE: 05.03.2003 CMNT: opd OBEX Event processing. */ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * */ #ifndef OBEX_HANDLER_H_INCLUDED #define OBEX_HANDLER_H_INCLUDED 1 void Handle_OBEX_Event(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp); #endif ./main.c0100666000000000000000000003403007635636010011014 0ustar rootroot/* CPRY: (C)2003 Beier & Dauskardt IT (www.bdit.de) FILE: main.c DATE: 05.03.2003 AUTH: S.Dauskardt CMNT: opd (OPEX Push Daemon) - main entry. TODO: check if sdp entry is already present. - Heavily based on BlueZ + OpenOBEX Thanks to all contributors ! */ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * */ const char *VERSION = "0.2"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lib.h" #include "obex_handler.h" #include "main.h" // Ugly globals.. // int srv_RFCommChannel; int srv_Modes; int srv_Daemonize; int srv_Debug; int srv_AddSDP; int srv_Metadata; char srv_BasePath[256]; // Bits possibly missing in sdp.h // #ifndef BIP_SVCLASS_ID #define BIP_SVCLASS_ID 0x111b // Responder #endif #ifndef BIP_PROFILE_ID #define BIP_PROFILE_ID 0x111a #endif int OPD_SocketType() { if( srv_Modes & (OPDM_OBEX|OPDM_BIP) ) return AF_BLUETOOTH; if( srv_Modes & (OPDM_IRDA) ) return AF_IRDA; return 0; } // // // sdp_record_t obex_record; int add_opush(sdp_session_t *session) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[3]; uint8_t u8 = srv_RFCommChannel; sdp_data_t *channel; memset((void *)&obex_record, 0, sizeof(sdp_record_t)); obex_record.handle = 0xffffffff; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&obex_record, root); sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID); svclass_id = sdp_list_append(0, &opush_uuid); sdp_set_service_classes(&obex_record, svclass_id); sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(0, profile); sdp_set_profile_descs(&obex_record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); sdp_uuid16_create(&obex_uuid, OBEX_UUID); proto[2] = sdp_list_append(0, &obex_uuid); apseq = sdp_list_append(apseq, proto[2]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&obex_record, aproto); sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(proto[2], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); sdp_set_info_attr(&obex_record, "OBEX Object Push", 0, 0); /* Add Supported Formats List Attribute (0x0303) */ { uint8_t uint8 = SDP_UINT8; uint8_t formats[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xFF}; void **dtds = (void **)malloc (sizeof (formats) * sizeof(void *)); void **values = (void **)malloc (sizeof (formats) * sizeof(void *)); int i; sdp_data_t *seq; for(i = 0; i < sizeof (formats); i++){ dtds[i] = &uint8; values[i] = &formats [i]; } seq = sdp_seq_alloc (dtds, values, sizeof (formats)); sdp_attr_add(&obex_record, 0x303, seq); free (dtds); free (values); } if (0 > sdp_record_register(session, &obex_record, SDP_RECORD_PERSIST)) { syslog(LOG_ERR,"OBEX Object Push Service Record registration failed with sdpd.\n"); return -1; } syslog(LOG_INFO,"OBEX Object Push service registered with sdpd\n"); return 0; } // // // sdp_record_t bip_record; int add_bip(sdp_session_t *session) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[3]; uint8_t u8 = srv_RFCommChannel; sdp_data_t *channel; memset((void *)&bip_record, 0, sizeof(sdp_record_t)); bip_record.handle = 0xffffffff; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&bip_record, root); sdp_uuid16_create(&opush_uuid, BIP_SVCLASS_ID); svclass_id = sdp_list_append(0, &opush_uuid); sdp_set_service_classes(&bip_record, svclass_id); sdp_uuid16_create(&profile[0].uuid, BIP_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(0, profile); sdp_set_profile_descs(&bip_record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &u8); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); sdp_uuid16_create(&obex_uuid, OBEX_UUID); // nicht BIP !!! proto[2] = sdp_list_append(0, &obex_uuid); apseq = sdp_list_append(apseq, proto[2]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&bip_record, aproto); sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(proto[2], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); sdp_set_info_attr(&bip_record, "BIP", 0, 0); /* Add Supported capabilities (0x0310) */ { uint8_t uint8 = SDP_UINT8; uint8_t capabilities = 0x01; void *dtds[1]; void *values[1]; sdp_data_t *seq; dtds[0] = &uint8; values[0] = &capabilities; seq = sdp_seq_alloc (dtds, values, 1); //sizeof (formats)); sdp_attr_add(&bip_record, 0x310, seq); } { uint16_t uint16 = SDP_UINT16; uint16_t capabilities = 0x01; void *dtds[1]; void *values[1]; sdp_data_t *seq; dtds[0] = &uint16; values[0] = &capabilities; seq = sdp_seq_alloc (dtds, values, 1); sdp_attr_add(&bip_record, 0x311, seq); } { uint32_t uint32 = SDP_UINT32; uint32_t capabilities = 0x03; void *dtds[1]; void *values[1]; sdp_data_t *seq; dtds[0] = &uint32; values[0] = &capabilities; seq = sdp_seq_alloc (dtds, values, 1); sdp_attr_add(&bip_record, 0x312, seq); } { uint64_t uint64 = SDP_UINT64; uint64_t capabilities = 8*1024*1024; void *dtds[1]; void *values[1]; sdp_data_t *seq; dtds[0] = &uint64; values[0] = &capabilities; seq = sdp_seq_alloc (dtds, values, 1); sdp_attr_add(&bip_record, 0x313, seq); } if (0 > sdp_record_register(session, &bip_record, SDP_RECORD_PERSIST)) { syslog(LOG_ERR,"BIP Service Record registration failed with sdpd.\n"); return -1; } syslog(LOG_INFO,"BIP service registered with sdpd\n"); return 0; } /* Add local service */ int AddSDPService() { int ret = 0; sdp_session_t *sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!sess){ syslog(LOG_ERR, "Failed to connect to SDP server.\n"); return -1; } if( srv_Modes & OPDM_OBEX ){ ret = add_opush(sess); } if( srv_Modes & OPDM_BIP ){ ret = add_bip(sess); } sdp_close(sess); return ret; } int RemoveSDPService() { int ret=0; sdp_session_t *sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!sess){ syslog(LOG_ERR, "Failed to connect to SDP server.\n"); return -1; } if( srv_Modes & OPDM_OBEX ){ ret = sdp_record_unregister(sess, &obex_record); } if( srv_Modes & OPDM_BIP ){ ret = sdp_record_unregister(sess, &bip_record); } if( 0 > ret ){ syslog(LOG_ERR,"Service Record unregistration failed with sdpd.\n"); }else{ syslog(LOG_INFO,"service unregistered with sdpd\n"); } sdp_close(sess); return ret; } void sig_term(int sig) { syslog(LOG_INFO,"Terminating .. \n"); if( srv_AddSDP ) RemoveSDPService(); // TODO: OBEX_Cleanup ?? exit(0); } // void obex_event(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp); void printusage() { printf("Basic Imaging Profile - Image responder daemon (c)2003 bdit.de\n"); printf("Usage:\n"); printf("opd [option [arg]] [option [arg]]...\n"); printf("\n"); printf(" options:\n"); printf("\n"); printf(" --mode < BIP | OBEX | BIP+OBEX | IRDA >\n"); printf(" Run in plain OBEX, extended BIP mode, both or IrDA (default: OBEX).\n"); printf("\n"); printf(" --path \n"); printf(" Path where to save recieved files to (default: /tmp)\n"); printf("\n"); printf(" --channel \n"); printf(" RFCOMM channel.\n"); printf("\n"); printf(" --sdp\n"); printf(" Register with sdpd.\n"); printf("\n"); printf(" --metadata\n"); printf(" Save metadata with recieved files.\n"); printf("\n"); printf(" --daemonize\n"); printf(" Run in background.\n"); printf("\n"); } int main(int argc, char **argv,char *env[]) { obex_t *server_handle = NULL; int err; int fd,i; if( argc < 2 ){ printusage(); exit(0); } srv_RFCommChannel = 1; srv_Modes = OPDM_OBEX; srv_Daemonize = 0; srv_Debug = 0; srv_AddSDP = 0; srv_Metadata = 0; strcpy(srv_BasePath,"/tmp/"); // Read commandline. // for(i=1;i