📄 upnphosting.java
字号:
System.out.println("Request is UNSUBSCRIBE");
req.requestMethod = REQUEST_METHOD_UNSUBSCRIBE;
response = handleUnsubscribeRequest(req);
*/
} else {
time = System.currentTimeMillis();
System.out.println("[" + Thread.currentThread()+ "][" + time +"] Unknown request method");
StringBuffer responseBuf = new StringBuffer(2048);
responseBuf.append("HTTP/1.1 501 Not Implemented\r\n");
responseBuf.append("Connection: close\r\n");
responseBuf.append("Content-Length: 0\r\n");
responseBuf.append("\r\n");
response = responseBuf.toString().getBytes();
}
}
/* XXX Should use exceptions for error conditions instead
if (response == null) {
StringBuffer responseBuf = new StringBuffer(2048);
responseBuf.append(
"HTTP/1.1 500 Internal Server Error\r\n");
responseBuf.append("Content-Length: 0\r\n");
responseBuf.append("Date: ");
responseBuf.append(Utilities.getRfcDateString(
Calendar.getInstance(TimeZone.getTimeZone("GMT"))));
responseBuf.append("\r\n");
responseBuf.append("\r\n");
response = responseBuf.toString().getBytes();
}
*/
if (response != null) {
OutputStream os = sc.openOutputStream();
os.write(response);
os.close();
}
} catch (Exception e) {
long time = System.currentTimeMillis();
System.out.println("[" + Thread.currentThread()+ "][" + time +"] Exception occured in UPnPHosting::ConnectionHandler");
LOG.warn(e);
e.printStackTrace();
} finally {
try {
sc.close();
} catch (Exception e) {
LOG.debug("[" + Thread.currentThread()+ "] Error closing this connection");
}
decrementNumRequestsHandling();
long time = System.currentTimeMillis();
System.out.println("[" + Thread.currentThread()+ "][" + time +"] Finished handling the request");
}
}
/**
* Creates a hashtable with the headers from the request.
*
* @return Hashtable with key=header-name and value=header-value
*/
private void setRequestHeaders(String request, HttpRequest req) {
//
// Create a hashtable of the headers
// XXX Could try to rewrite the while-loop to use the request
// instead, so this step won't be required.
// 1) Must start at request.indexOf("\r\n") + 2
// 2) Must end before "\r\n\r\n"
String headersText = request.substring(
request.indexOf("\r\n") + 2,
request.indexOf("\r\n\r\n") + 1);
int prevPos = 0, pos = 0;
while ((pos = headersText.indexOf(':', prevPos)) >= 0) {
String header = headersText.substring(prevPos, pos).trim();
prevPos = pos;
pos = headersText.indexOf('\r', pos);
String headerValue = headersText.substring(prevPos + 1, pos).trim();
req.setHeader(header, headerValue);
prevPos = pos;
}
}
}
/**
* Register a handler for GET requests for a specific namespace.
*
* This method makes it possible to have a namespace, such as /device or
* /content, be controlled by different handler objects which knows how
* to handle requests to this namespace.
*
* @param namespace Which namespace to handle by this handler
*
* @param handler Object which will handle requests to this namespace.
*
* @return If this namespace was not handled earlier then null, otherwise
* the object of the old handler.
*/
public HttpRequestHandler registerHttpHandler(
String namespace,
HttpRequestHandler handler)
{
return (HttpRequestHandler)httpRequestHandlers.put(namespace, handler);
}
/**
* Is a namespace handled by someone?
*/
public boolean isNamespaceHandled(String namespace) {
return httpRequestHandlers.containsKey(namespace);
}
/**
* Get namespace handler.
*/
public HttpRequestHandler getHttpRequestHandlerForNamespace(String namespace) {
return (HttpRequestHandler)httpRequestHandlers.get(namespace);
}
/**
* Remove HTTP Request handler.
*
* @param namespace Namespace of the HTTP request handler to remove.
*
* @return HTTP Request handler of this namespace.
*/
public HttpRequestHandler removeHttpRequestHandler(String namespace) {
return (HttpRequestHandler)httpRequestHandlers.remove(namespace);
}
/**
* Generates description documents.
*
* Will create a device description document and one service description
* document for each service offered by the device.
*/
public void registerDevice(UPnPHostingDevice device) {
try {
int recordId = -1;
/* XXX Unfortunately get ArrayIndexOutOfBoundsException due to enumerating the
cache here :/
//
// Check if device desc is already cached
//
if (descriptionDocumentCache.getNumRecords() > 0) {
RecordEnumeration re = descriptionDocumentCache.enumerateRecords(
new DeviceFilter(device.udn()),
null,
true);
System.out.println("RecordEnumeration created");
/*
Can not use the following code until the port number is static,
because the device description contains the URL Base which
contains IP address + port number
if (!re.hasNextElement()) {
System.out.println(
"Device description does not exist yet. Generating it now.");
String devDesc = generateDeviceDescription(device);
byte[] desc = devDesc.getBytes();
recordId = descriptionDocumentCache.addRecord(desc, 0, desc.length);
} else {
System.out.println("Number of records found: " + re.numRecords());
recordId = re.nextRecordId();
}
*x/
//
// Delete the cache if it already exists
//
if (re.hasNextElement()) {
System.out.println("Seems like the device already exists in the cache");
descriptionDocumentCache.deleteRecord(re.nextRecordId());
System.out.println("Device deleted from record store");
}
re.destroy();
}
*/
String devDesc = generateDeviceDescription(device);
byte[] desc = devDesc.getBytes();
recordId = descriptionDocumentCache.addRecord(desc, 0, desc.length);
//
// Generate service description documents
for (Enumeration e = device.serviceTable().elements();
e.hasMoreElements(); )
{
UPnPHostingService service = (UPnPHostingService)e.nextElement();
desc = generateServiceDescription(service).getBytes();
int serviceRecordId = descriptionDocumentCache.addRecord(
desc,
0,
desc.length);
entities.put(
service.serviceId().replace(':', '_'),
new HostingCacheContainer(
serviceRecordId,
service));
}
entities.put(
device.udn().replace(':', '_'),
new HostingCacheContainer(recordId, device));
//
// Schedule a timer to send notifications about the device +
// services.
//
notificationTimer.schedule(new DeviceNotificationTask(device), 0, notifyPeriod * 1000);
} catch (RecordStoreNotOpenException rsnoe) {
LOG.fatal(rsnoe);
} catch (RecordStoreException rse) {
LOG.fatal(rse);
}
}
private final class DeviceFilter implements RecordFilter {
private String udn;
public DeviceFilter(String udn) {
System.out.println("DeviceFilter ctor: " + udn);
this.udn = udn;
}
public boolean matches(byte[] candidate) {
System.out.println("Check if candidate matches device UDN(" + udn + ")");
String desc = new String(candidate);
return (desc.indexOf(udn) != -1) ? true : false;
}
}
/**
* Sends a ssdp:alive message for the device associated with this
* instance.
*/
private final class DeviceNotificationTask extends TimerTask {
private UPnPHostingDevice device;
public DeviceNotificationTask(UPnPHostingDevice device) {
this.device = device;
}
public void run() {
/*
When a device is added to the network, it multicasts discovery
messages to advertise its root device, to advertise any
embedded devices, and to advertise its services.
To advertise its capabilities, a device multicasts a number of discovery messages.
Specifically, a root device must multicast:
Three discovery messages for the root device.
1 root device UUID ** root device UUID
2 device type : device version root device UUID and ::
and device type : device version
3 upnp:rootdevice root device UUID and :: and
upnp:rootdevice
Two discovery messages for each embedded device.
1 embedded device UUID ** embedded device UUID
2 device type : device version embedded device UUID and :: and device
type : device version
Once for each service.
1 service type : service version enclosing device UUID and :: and service
type : service version
*/
try {
Hashtable serviceTable = device.serviceTable();
// Calculate the amount of packets to send
//
int numMsgsNeeded = 3 + serviceTable.size(); // Drop embedded devices
String[][] headerPairsNtAndUsn = new String[numMsgsNeeded][2];
//
// NT = root device UUID
headerPairsNtAndUsn[0] = new String[]{
device.udn(),
device.udn()};
//
// NT = device type : device version
headerPairsNtAndUsn[1] = new String[]{
device.deviceType(),
device.udn() + "::" + device.deviceType()};
//
// NT = upnp:rootdevice
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -