📄 mmscp.c
字号:
long ipq[4]; int qi; unsigned long ip,reverseThis; char *rp; int cmpIp1, cmpIp2; int badUri; /* * copy the list of protocolInfo strings into protInfoSet */ protInfoSetStringLen = (int) strlen(protocolInfoSet); protInfoSetStringSize = protInfoSetStringLen + 1; protInfoSet = (char*) malloc (protInfoSetStringSize); memcpy(protInfoSet, protocolInfoSet, protInfoSetStringSize); protInfoSet[protInfoSetStringLen] = '\0'; /* * Replace all commas in protInfoSet to NULL chars * and count the number of protocolInfo strings in the set. * Method only works if the protocolInfo are listed in form: A,B,...Z. * If we receive malformed sets like A,,B then results are undefined. */ protInfoCount = 1; for (i=0; i < protInfoSetStringLen; i++) { if (protInfoSet[i] == ',') { protInfoSet[i] = '\0'; protInfoCount++; } } /* * create an array of char** that will allow us easy access * to individual protocolInfo. Also redo the count * in case of inaccuracies due to bad formatting. */ protInfos = (char**) malloc (sizeof(char*) * protInfoCount); pi = 0; finding = 0; for (i=0; i < protInfoSetStringLen; i++) { if ((finding == 0) && (protInfoSet[i] != '\0')) { protInfos[pi] = &(protInfoSet[i]); pi++; finding = 1; protInfoCount++; } else if ((finding == 1) && (protInfoSet[i] == '\0')) { finding = 0; } } if (pi < protInfoCount) { protInfoCount = pi; } /* * Iterate through the different resources and track the best match. */ res = mediaObj->Res; while (res != NULL) { /* the protocolInfo strings listed first have higher precedence */ protInfoMatch = protInfoCount + 1; /* calculate a match value against protocolInfo */ for (i=0; i < protInfoCount; i++) { protInfoMatch--; /* * get pointers and lengths for the fields in the protocolInfo */ protocol = protInfos[i]; protocolLen = IndexOf(protocol, ":"); network = protocol + protocolLen + 1; networkLen = IndexOf(network, ":"); mimeType = network + networkLen + 1; mimeTypeLen = IndexOf(mimeType, ":"); info = mimeType + mimeTypeLen + 1; infoLen = (int) strlen(info); /* * get pointers and lengths for the fields in the resource's protocolInfo */ resprotocol = res->ProtocolInfo; resprotocolLen = IndexOf(resprotocol, ":"); resnetwork = resprotocol + resprotocolLen + 1; resnetworkLen = IndexOf(resnetwork, ":"); resmimeType = resnetwork + resnetworkLen + 1; resmimeTypeLen = IndexOf(resmimeType, ":"); resinfo = resmimeType + resmimeTypeLen + 1; resinfoLen = (int) strlen(resinfo); /* compare each of the fields */ if (strnicmp(protocol, resprotocol, MIN(protocolLen, resprotocolLen)) == 0) { if (strnicmp(network, resnetwork, MIN(networkLen, resnetworkLen)) == 0) { if ( ((mimeType[0] == '*') && (mimeType[1] == ':')) || (strnicmp(mimeType, resmimeType, MIN(mimeTypeLen, resmimeTypeLen)) == 0) ) { /* * DHWG guidelines require the DLNA.ORG_PN parameter to * show up first, so this code will work provided * the protocolInfo values in protocolInfoSet only * have the DLNA.ORG_PN parameter in it. It's OK if * the CdsMediaResource has other parameters because * we only compare MIN(infoLen,resinfoLen). */ if ( ((info[0] == '*') && (info[1] == '\0')) || (strnicmp(info, resinfo, MIN(infoLen, resinfoLen)) == 0) ) { /* * If we get here then protocolInfo matches. * Go ahead and break since protInfoMatch is * set on every iteration. */ break; } } } } } /* * At this point, we have calculated the protInfoMatch value, * but we still need to determine if the resource has a good * chance of being routable given a particular target * IP address. */ ipMatch = 0xFFFFFFFF; ip = 0; /* * Convert text-based IP address to in-order int form. * Since the res->URI is assumed to be a valid DLNA URI, * it will have the form scheme://[ip address]:.... * * If by chance the URI is not in quad-notation, then we * use an IP address value of 0.0.0.0 because it's impossible * to match with host/domain names. */ posIpByteStart = IndexOf(res->Uri, "://") + 3; if (posIpByteStart > 0) { rp = res->Uri + posIpByteStart; qi = 0; badUri = 0; while ((qi < 4) && (badUri == 0)) { posIpByteLength = 0; /* loop until we don't find a digit or until we know it's a bad URI*/ while ((isdigit(rp[posIpByteLength]) != 0) || (badUri != 0)) { posIpByteLength++; if (posIpByteLength > 3) { badUri = 1; } } if (posIpByteLength == 0) badUri = 1; if (badUri == 0) { ILibGetLong(rp, posIpByteLength, &(ipq[qi])); if (ipq[qi] > 255) badUri = 1; rp += (posIpByteLength + 1); qi++; } } if (badUri != 0) { ipq[0] = ipq[1] = ipq[2] = ipq[3] = 0; } } /* * Convert each network byte into a 32-bit integer, * then perform a bit mask comparison against the target ip address. */ ip = (int) (ipq[0] | (ipq[1] << 8) | (ipq[2] << 16) | (ipq[3] << 24)); cmpIp1 = htonl(ip); for (i=0; i < ipAddressListLen; i++) { cmpIp2 = htonl(ipAddressList[i]); reverseThis = (cmpIp2 ^ ip); ipMatch = ((reverseThis & 0x000000ff) << 24) | ((reverseThis & 0x0000ff00) << 8) | ((reverseThis & 0x00ff0000) >> 8) | ((reverseThis & 0xff000000) >> 24); if ( ((unsigned)ipMatch < (unsigned)bestIpMatch) || ((ipMatch == bestIpMatch) && (protInfoMatch > bestProtInfoMatch)) ) { retVal = res; bestIpMatch = ipMatch; bestProtInfoMatch = protInfoMatch; } } res = res->Next; } free (protInfos); free (protInfoSet); return retVal;}void MMSCP_Uninit(void){ MMSCP_Callback_Browse = NULL; MMSCP_Callback_DeviceAddRemove = NULL;}struct MMSCP_MediaObject *MMSCP_CloneMediaObject(const struct MMSCP_MediaObject *cloneThis){ /* * This code is written for both 64-bit and 32-bit address spaces. */ #define ADDRESS_SPACE 64 #if (ADDRESS_SPACE==64) #define MEMTYPE long #else #define MEMTYPE long #endif struct MMSCP_MediaObject *retVal = NULL; const struct MMSCP_MediaObject *ct; struct MMSCP_MediaObject **ah; MEMTYPE diff; struct MMSCP_MediaResource *ctr, **clr; int dataSize, mallocSize = 0; char *di, *emptyDI; //char dbgstr[1024]; ah = &(retVal); ct = cloneThis; if (ct != NULL) { if (ct->MallocSize == 0) { dataSize = MMSCP_GetRequiredSizeForMediaObject((struct MMSCP_MediaObject *)ct, (struct MMSCP_MediaObject *)NULL); mallocSize = dataSize + sizeof(struct MMSCP_MediaObject) + 1; (*ah) = (struct MMSCP_MediaObject*) malloc(mallocSize); memset((*ah), 0, mallocSize); (*ah)->MallocSize = mallocSize; (*ah)->RefCount = 0; //sprintf(dbgstr, "CL1: %x(%s)\r\n", (*ah), ct->ID); //OutputDebugString(dbgstr); (*ah)->MediaClass = ct->MediaClass; (*ah)->Flags = ct->Flags; /* di will point to where it's safe to write string data */ di = (char*)(*ah); di += sizeof(struct MMSCP_MediaObject); emptyDI = di; di ++; MMSCP_StringFixup(&((*ah)->ID), &di, emptyDI, ct->ID, ct->ID, ct->ID); MMSCP_StringFixup(&((*ah)->ParentID), &di, emptyDI, ct->ParentID, ct->ParentID, ct->ParentID); MMSCP_StringFixup(&((*ah)->RefID), &di, emptyDI, ct->RefID, ct->RefID, ct->RefID); MMSCP_StringFixup(&((*ah)->Title), &di, emptyDI, ct->Title, ct->Title, ct->Title); MMSCP_StringFixup(&((*ah)->Creator), &di, emptyDI, ct->Creator, ct->Creator, ct->Creator); MMSCP_StringFixup(&((*ah)->Genre), &di, emptyDI, ct->Genre, ct->Genre, ct->Genre); MMSCP_StringFixup(&((*ah)->Album), &di, emptyDI, ct->Album, ct->Album, ct->Album); ctr = ct->Res; clr = &((*ah)->Res); while (ctr != NULL) { (*clr) = (struct MMSCP_MediaResource*) malloc (sizeof(struct MMSCP_MediaResource)); memcpy((*clr), ctr, sizeof(struct MMSCP_MediaResource)); MMSCP_StringFixup(&((*clr)->ProtocolInfo), &di, emptyDI, ctr->ProtocolInfo, ctr->ProtocolInfo, ctr->ProtocolInfo); MMSCP_StringFixup(&((*clr)->Resolution), &di, emptyDI, ctr->Resolution, ctr->Resolution, ctr->Resolution); MMSCP_StringFixup(&((*clr)->Uri), &di, emptyDI, ctr->Uri, ctr->Uri, ctr->Uri); ctr = ctr->Next; } /* prevent memory corruption in debug version */ ASSERT(di <= ((char*)(*ah)) + mallocSize); } else { /* allocate memory for the cloned CDS object and copy its state*/ (*ah) = (struct MMSCP_MediaObject*) malloc(ct->MallocSize); diff = ((unsigned MEMTYPE)retVal - (unsigned MEMTYPE)cloneThis); memcpy((*ah), ct, ct->MallocSize); /* * Initialize stuff that is unique to this * particular instance - notably, the reserved fields. */ if ((*ah)->ServiceObject != NULL) { MMSCP_AddRefRootDevice((*ah)->ServiceObject); } (*ah)->RefCount = 0; /* we will clone resources in another step */ (*ah)->Res = NULL; /* * Adjust the pointer addresses so that they fit for the new CDS object. * ignore compiler warnings */ ((struct MMSCP_MediaObject*)*ah)->Album = (char *)(((unsigned MEMTYPE) ((*ah)->Album)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->Creator = (char *)(((unsigned MEMTYPE) ((*ah)->Creator)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->Genre = (char *)(((unsigned MEMTYPE) ((*ah)->Genre)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->ID = (char *)(((unsigned MEMTYPE) ((*ah)->ID)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->ParentID = (char *)(((unsigned MEMTYPE) ((*ah)->ParentID)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->RefID = (char *)(((unsigned MEMTYPE) ((*ah)->RefID)) + (diff)); ((struct MMSCP_MediaObject*)*ah)->Title = (char *)(((unsigned MEMTYPE) ((*ah)->Title)) + (diff)); /* * Clone resources. * Note that memory for resource strings is part of the CDS object * because some of those strings may repeat. Thus, all we need * to do is allocate memory for the CDS resource, copy as is, * and then adjust the string pointers. */ ctr = ct->Res; clr = &((*ah)->Res); while (ctr != NULL) { /* allocate and copy */ (*clr) = (struct MMSCP_MediaResource*) malloc (sizeof(struct MMSCP_MediaResource)); memcpy((*clr), ctr, sizeof(struct MMSCP_MediaResource)); /* adjust string pointers - remember that they point to memory that trails the CDS object */ ((struct MMSCP_MediaResource*)*clr)->Uri = (char *)(((unsigned MEMTYPE) ((*clr)->Uri)) + (diff)); ((struct MMSCP_MediaResource*)*clr)->ProtocolInfo = (char *)(((unsigned MEMTYPE) ((*clr)->ProtocolInfo)) + (diff)); ((struct MMSCP_MediaResource*)*clr)->Resolution = (char *)(((unsigned MEMTYPE) ((*clr)->Resolution)) + (diff)); clr = &((*clr)->Next); ctr = ctr->Next; } } } return retVal;}void MMSCP_ObjRef_Add(struct MMSCP_MediaObject *refThis){ //char dbgstr[1024]; //sprintf(dbgstr, "OB+: %x\t(%s)(%d)\r\n", refThis, refThis->ID, refThis->RefCount); //OutputDebugString(dbgstr); refThis->RefCount++;}void MMSCP_ObjRef_Release(struct MMSCP_MediaObject *releaseThis){ struct MMSCP_MediaResource *res; struct MMSCP_MediaResource *nextRes; //char dbgstr[1024]; /* * Remember that the ResultsList is stored in such a way that * each MediaObject and MediaResource pointer is allocated * with additional trailinng memory that stores the strings associated * with the object. Therefore, when we free a MediaResource or * a MediaObject, we're also freeing the memory for the string metadata. */ if (releaseThis != NULL) { //sprintf(dbgstr, "OB-: %x\t(%s)(%d)\r\n", releaseThis, releaseThis->ID, releaseThis->RefCount); //OutputDebugString(dbgstr); releaseThis->RefCount--; if (releaseThis->RefCount <= 0) { res = releaseThis->Res; while (res != NULL) { nextRes = res->Next; MMSCP_FREE(res); res = nextRes; } if (releaseThis->ServiceObject != NULL) { /* release the UPnP device */ MMSCP_ReleaseRootDevice(releaseThis->ServiceObject); } /* destroy the object */ MMSCP_FREE(releaseThis); } else { } }}/*********************************************************************************************************************** * END: API method implementations ***********************************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -