/* * Returns a PayloadType from the local list that matches a PayloadType offered or answered in the remote list */ static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){ PayloadTypeMatcher *m; for(m=matchers;m->mime_type!=NULL;++m){ if (refpt->mime_type && strcasecmp(m->mime_type,refpt->mime_type)==0){ return m->match_func(l,refpt); } } return generic_match(l,refpt); }
/* * Returns a PayloadType from the local list that matches a PayloadType offered or answered in the remote list */ static PayloadType * find_payload_type_best_match(MSFactory *factory, const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads, bool_t reading_response){ PayloadType *ret = NULL; MSOfferAnswerContext *ctx = ms_factory_create_offer_answer_context(factory, refpt->mime_type); if (ctx){ ms_message("Doing offer/answer processing with specific provider for codec [%s]", refpt->mime_type); ret = ms_offer_answer_context_match_payload(ctx, local_payloads, refpt, remote_payloads, reading_response); ms_offer_answer_context_destroy(ctx); return ret; } return generic_match(local_payloads, refpt, remote_payloads); }
/** * @brief Handle inotify events * * Calls the callcbacks * * @param files nb max of logs destination directories (crashlog, * aplogs, bz... ) * * @return 0 on success, -1 on error. */ int receive_inotify_events(int inotify_fd) { int len = 0, orig_len, idx, wd, missing_bytes; char orig_buffer[sizeof(struct inotify_event)+PATHMAX], *buffer, lastevent[sizeof(struct inotify_event)+PATHMAX]; struct inotify_event *event; struct watch_entry *entry = NULL; len = read(inotify_fd, orig_buffer, sizeof(orig_buffer)); if (len < 0) { LOGE("%s: Cannot read file_monitor_fd, error is %s\n", __FUNCTION__, strerror(errno)); return -errno; } buffer = &orig_buffer[0]; orig_len = len; event = (struct inotify_event *)buffer; /* Preinitialize lastevent (in case it was not used so it is not dumped) */ ((struct inotify_event *)lastevent)->wd = 0; ((struct inotify_event *)lastevent)->mask = 0; ((struct inotify_event *)lastevent)->cookie = 0; ((struct inotify_event *)lastevent)->len = 0; while (1) { if (len == 0) { /* End of the events to read */ return 0; } if ((unsigned int)len < sizeof(struct inotify_event)) { /* Not enough room for an empty event */ LOGI("%s: incomplete inotify_event received (%d bytes), complete it\n", __FUNCTION__, len); /* copy the last bytes received */ if( (unsigned int)len <= sizeof(lastevent) ) memcpy(lastevent, buffer, len); else { LOGE("%s: Cannot copy buffer\n", __FUNCTION__); return -1; } /* read the missing bytes to get the full length */ missing_bytes = (int)sizeof(struct inotify_event)-len; if(((int) len + missing_bytes) < ((int)sizeof(lastevent))) { if (read(inotify_fd, &lastevent[len], missing_bytes) != missing_bytes ){ LOGE("%s: Cannot complete the last inotify_event received (structure part) - %s\n", __FUNCTION__, strerror(errno)); return -1; } } else { LOGE("%s: Cannot read missing bytes, not enought space in lastevent\n", __FUNCTION__); return -1; } event = (struct inotify_event*)lastevent; /* now, reads the full last event, including its name field */ if ( read(inotify_fd, &lastevent[sizeof(struct inotify_event)], event->len) != (int)event->len) { LOGE("%s: Cannot complete the last inotify_event received (name part) - %s\n", __FUNCTION__, strerror(errno)); return -1; } len = 0; /* now, the last event is complete, we can continue the parsing */ } else if ( (unsigned int)len < sizeof(struct inotify_event) + event->len ) { int res, missing_bytes = (int)sizeof(struct inotify_event) + event->len - len; event = (struct inotify_event*)lastevent; /* The event was truncated */ LOGI("%s: truncated inotify_event received (%d bytes missing), complete it\n", __FUNCTION__, missing_bytes); /* Robustness : check 'lastevent' array size before reading inotify fd*/ if( (unsigned int)len > sizeof(lastevent) ) { LOGE("%s: not enough space on array lastevent.\n", __FUNCTION__); return -1; } /* copy the last bytes received */ memcpy(lastevent, buffer, len); /* now, reads the full last event, including its name field */ res = read(inotify_fd, &lastevent[len], missing_bytes); if ( res != missing_bytes ) { LOGE("%s: Cannot complete the last inotify_event received (name part2); received %d bytes, expected %d bytes - %s\n", __FUNCTION__, res, missing_bytes, strerror(errno)); return -1; } len = 0; /* now, the last event is complete, we can continue the parsing */ } else { event = (struct inotify_event *)buffer; buffer += sizeof(struct inotify_event) + event->len; len -= sizeof(struct inotify_event) + event->len; } /* Handle the event read from the buffer*/ /* First check the kind of the subject of this event (file or directory?) */ if (!(event->mask & IN_ISDIR)) { /* event concerns a file into a watched directory */ entry = get_event_entry(event->wd, (event->len ? event->name : NULL)); if ( !entry ) { /* Didn't find any entry for this event, check for * a dropbox final event... */ if (event->len > 8 && !strncmp(event->name, "dropbox-", 8)) { /* dumpstate is done so remove the watcher */ LOGD("%s: Received a dropbox event(%s)...", __FUNCTION__, event->name); inotify_rm_watch(inotify_fd, event->wd); finalize_dropbox_pending_event(event); continue; } /* Stray event... */ LOGD("%s: Can't handle the event \"%s\", no valid entry found, drop it...\n", __FUNCTION__, (event->len ? event->name : "empty event")); continue; } } /*event concerns a watched directory itself */ else { entry = NULL; /* Manage case where a watched directory is deleted*/ if ( event->mask & (IN_DELETE_SELF | IN_MOVE_SELF) ) { /* Recreate the dir and reinstall the watch */ for (idx = 0 ; idx < (int)DIM(wd_array) ; idx++) { if ( wd_array[idx].wd == event->wd ) entry = &wd_array[idx]; } if ( entry && entry->eventpath ) { mkdir(entry->eventpath, 0777); /* TO DO : restoring previous rights/owner/group ?*/ inotify_rm_watch(inotify_fd, event->wd); wd = inotify_add_watch(inotify_fd, entry->eventpath, entry->eventmask); if ( wd < 0 ) { LOGE("Can't add watch for %s.\n", entry->eventpath); return -1; } LOGW("%s: watched directory %s : \'%s\' has been created and snooped",__FUNCTION__, (event->mask & (IN_DELETE_SELF) ? "deleted" : "moved"), entry->eventpath); /* if the watch was duplicated, set it for all the entries */ for (idx = 0 ; idx < (int)DIM(wd_array) ; idx++) { if (wd_array[idx].wd == event->wd) wd_array[idx].wd = wd; } /* Do nothing more on directory events */ continue; } } else { for (idx = 0 ; idx < (int)DIM(wd_array) ; idx++) { if ( wd_array[idx].wd != event->wd ) continue; entry = &wd_array[idx]; /* for modem generic */ /* TO IMPROVE : change flag management and put this in main loop */ if(strstr(LOGS_MODEM_DIR, entry->eventpath) && (generic_match(event->name, g_first_modem_config))){ process_modem_generic(entry, event, inotify_fd); break; } } pconfig check_config = generic_match_by_wd(event->name, g_first_modem_config, event->wd); if(check_config){ process_modem_generic( &check_config->wd_config, event, inotify_fd); }else{ LOGE("%s: Directory not catched %s.\n", __FUNCTION__, event->name); } /* Do nothing more on directory events */ continue; } } if ( entry && entry->pcallback && entry->pcallback(entry, event) < 0 ) { LOGE("%s: Can't handle the event %s...\n", __FUNCTION__, event->name); dump_inotify_events(orig_buffer, orig_len, lastevent); return -1; } } return 0; }