001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.jk.common;
018:
019: import java.io.File;
020: import java.io.FileOutputStream;
021: import java.io.IOException;
022: import java.io.CharConversionException;
023: import java.net.InetAddress;
024: import java.util.Properties;
025: import javax.management.ObjectName;
026:
027: import org.apache.commons.modeler.Registry;
028: import org.apache.coyote.Request;
029: import org.apache.coyote.RequestGroupInfo;
030: import org.apache.coyote.RequestInfo;
031: import org.apache.coyote.Response;
032: import org.apache.coyote.Constants;
033: import org.apache.jk.core.JkHandler;
034: import org.apache.jk.core.Msg;
035: import org.apache.jk.core.MsgContext;
036: import org.apache.jk.core.WorkerEnv;
037: import org.apache.jk.core.JkChannel;
038: import org.apache.tomcat.util.buf.ByteChunk;
039: import org.apache.tomcat.util.buf.CharChunk;
040: import org.apache.tomcat.util.buf.HexUtils;
041: import org.apache.tomcat.util.buf.MessageBytes;
042: import org.apache.tomcat.util.http.MimeHeaders;
043: import org.apache.tomcat.util.net.SSLSupport;
044: import org.apache.tomcat.util.threads.ThreadWithAttributes;
045:
046: /**
047: * Handle messages related with basic request information.
048: *
049: * This object can handle the following incoming messages:
050: * - "FORWARD_REQUEST" input message ( sent when a request is passed from the
051: * web server )
052: * - "RECEIVE_BODY_CHUNK" input ( sent by container to pass more body, in
053: * response to GET_BODY_CHUNK )
054: *
055: * It can handle the following outgoing messages:
056: * - SEND_HEADERS. Pass the status code and headers.
057: * - SEND_BODY_CHUNK. Send a chunk of body
058: * - GET_BODY_CHUNK. Request a chunk of body data
059: * - END_RESPONSE. Notify the end of a request processing.
060: *
061: * @author Henri Gomez [hgomez@apache.org]
062: * @author Dan Milstein [danmil@shore.net]
063: * @author Keith Wannamaker [Keith@Wannamaker.org]
064: * @author Costin Manolache
065: */
066: public class HandlerRequest extends JkHandler {
067: private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
068: .getLog(HandlerRequest.class);
069:
070: // XXX Will move to a registry system.
071:
072: // Prefix codes for message types from server to container
073: public static final byte JK_AJP13_FORWARD_REQUEST = 2;
074: public static final byte JK_AJP13_SHUTDOWN = 7;
075: public static final byte JK_AJP13_PING_REQUEST = 8;
076: public static final byte JK_AJP13_CPING_REQUEST = 10;
077:
078: // Prefix codes for message types from container to server
079: public static final byte JK_AJP13_SEND_BODY_CHUNK = 3;
080: public static final byte JK_AJP13_SEND_HEADERS = 4;
081: public static final byte JK_AJP13_END_RESPONSE = 5;
082: public static final byte JK_AJP13_GET_BODY_CHUNK = 6;
083: public static final byte JK_AJP13_CPONG_REPLY = 9;
084:
085: // Integer codes for common response header strings
086: public static final int SC_RESP_CONTENT_TYPE = 0xA001;
087: public static final int SC_RESP_CONTENT_LANGUAGE = 0xA002;
088: public static final int SC_RESP_CONTENT_LENGTH = 0xA003;
089: public static final int SC_RESP_DATE = 0xA004;
090: public static final int SC_RESP_LAST_MODIFIED = 0xA005;
091: public static final int SC_RESP_LOCATION = 0xA006;
092: public static final int SC_RESP_SET_COOKIE = 0xA007;
093: public static final int SC_RESP_SET_COOKIE2 = 0xA008;
094: public static final int SC_RESP_SERVLET_ENGINE = 0xA009;
095: public static final int SC_RESP_STATUS = 0xA00A;
096: public static final int SC_RESP_WWW_AUTHENTICATE = 0xA00B;
097:
098: // Integer codes for common (optional) request attribute names
099: public static final byte SC_A_CONTEXT = 1; // XXX Unused
100: public static final byte SC_A_SERVLET_PATH = 2; // XXX Unused
101: public static final byte SC_A_REMOTE_USER = 3;
102: public static final byte SC_A_AUTH_TYPE = 4;
103: public static final byte SC_A_QUERY_STRING = 5;
104: public static final byte SC_A_JVM_ROUTE = 6;
105: public static final byte SC_A_SSL_CERT = 7;
106: public static final byte SC_A_SSL_CIPHER = 8;
107: public static final byte SC_A_SSL_SESSION = 9;
108: public static final byte SC_A_SSL_KEYSIZE = 11;
109: public static final byte SC_A_SECRET = 12;
110: public static final byte SC_A_STORED_METHOD = 13;
111:
112: // Used for attributes which are not in the list above
113: public static final byte SC_A_REQ_ATTRIBUTE = 10;
114:
115: // Terminates list of attributes
116: public static final byte SC_A_ARE_DONE = (byte) 0xFF;
117:
118: // Translates integer codes to names of HTTP methods
119: public static final String[] methodTransArray = { "OPTIONS", "GET",
120: "HEAD", "POST", "PUT", "DELETE", "TRACE", "PROPFIND",
121: "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK",
122: "ACL", "REPORT", "VERSION-CONTROL", "CHECKIN", "CHECKOUT",
123: "UNCHECKOUT", "SEARCH", "MKWORKSPACE", "UPDATE", "LABEL",
124: "MERGE", "BASELINE-CONTROL", "MKACTIVITY" };
125: public static final int SC_M_JK_STORED = (byte) 0xFF;
126:
127: // id's for common request headers
128: public static final int SC_REQ_ACCEPT = 1;
129: public static final int SC_REQ_ACCEPT_CHARSET = 2;
130: public static final int SC_REQ_ACCEPT_ENCODING = 3;
131: public static final int SC_REQ_ACCEPT_LANGUAGE = 4;
132: public static final int SC_REQ_AUTHORIZATION = 5;
133: public static final int SC_REQ_CONNECTION = 6;
134: public static final int SC_REQ_CONTENT_TYPE = 7;
135: public static final int SC_REQ_CONTENT_LENGTH = 8;
136: public static final int SC_REQ_COOKIE = 9;
137: public static final int SC_REQ_COOKIE2 = 10;
138: public static final int SC_REQ_HOST = 11;
139: public static final int SC_REQ_PRAGMA = 12;
140: public static final int SC_REQ_REFERER = 13;
141: public static final int SC_REQ_USER_AGENT = 14;
142: // AJP14 new header
143: public static final byte SC_A_SSL_KEY_SIZE = 11; // XXX ???
144:
145: // Translates integer codes to request header names
146: public static final String[] headerTransArray = { "accept",
147: "accept-charset", "accept-encoding", "accept-language",
148: "authorization", "connection", "content-type",
149: "content-length", "cookie", "cookie2", "host", "pragma",
150: "referer", "user-agent" };
151:
152: /*
153: * Note for Host parsing.
154: */
155: public static final int HOSTBUFFER = 10;
156:
157: HandlerDispatch dispatch;
158: String ajpidDir = "conf";
159:
160: public HandlerRequest() {
161: }
162:
163: public void init() {
164: dispatch = (HandlerDispatch) wEnv.getHandler("dispatch");
165: if (dispatch != null) {
166: // register incoming message handlers
167: dispatch.registerMessageType(JK_AJP13_FORWARD_REQUEST,
168: "JK_AJP13_FORWARD_REQUEST", this , null); // 2
169:
170: dispatch.registerMessageType(JK_AJP13_SHUTDOWN,
171: "JK_AJP13_SHUTDOWN", this , null); // 7
172:
173: dispatch.registerMessageType(JK_AJP13_CPING_REQUEST,
174: "JK_AJP13_CPING_REQUEST", this , null); // 10
175: dispatch.registerMessageType(HANDLE_THREAD_END,
176: "HANDLE_THREAD_END", this , null);
177: // register outgoing messages handler
178: dispatch.registerMessageType(JK_AJP13_SEND_BODY_CHUNK, // 3
179: "JK_AJP13_SEND_BODY_CHUNK", this , null);
180: }
181:
182: bodyNote = wEnv.getNoteId(WorkerEnv.ENDPOINT_NOTE,
183: "jkInputStream");
184: tmpBufNote = wEnv.getNoteId(WorkerEnv.ENDPOINT_NOTE, "tmpBuf");
185: secretNote = wEnv.getNoteId(WorkerEnv.ENDPOINT_NOTE, "secret");
186:
187: if (next == null)
188: next = wEnv.getHandler("container");
189: if (log.isDebugEnabled())
190: log.debug("Container handler " + next + " "
191: + next.getName() + " " + next.getClass().getName());
192:
193: // should happen on start()
194: generateAjp13Id();
195: }
196:
197: public void setSecret(String s) {
198: requiredSecret = s;
199: }
200:
201: public void setUseSecret(boolean b) {
202: requiredSecret = Double.toString(Math.random());
203: }
204:
205: public void setDecodedUri(boolean b) {
206: decoded = b;
207: }
208:
209: public boolean isTomcatAuthentication() {
210: return tomcatAuthentication;
211: }
212:
213: public void setTomcatAuthentication(boolean newTomcatAuthentication) {
214: tomcatAuthentication = newTomcatAuthentication;
215: }
216:
217: public void setAjpidDir(String path) {
218: if ("".equals(path))
219: path = null;
220: ajpidDir = path;
221: }
222:
223: /**
224: * Set the flag to tell if we JMX register requests.
225: */
226: public void setRegisterRequests(boolean srr) {
227: registerRequests = srr;
228: }
229:
230: /**
231: * Get the flag to tell if we JMX register requests.
232: */
233: public boolean getRegisterRequests() {
234: return registerRequests;
235: }
236:
237: // -------------------- Ajp13.id --------------------
238:
239: private void generateAjp13Id() {
240: int portInt = 8009; // tcpCon.getPort();
241: InetAddress address = null; // tcpCon.getAddress();
242:
243: if (requiredSecret == null)
244: return;
245:
246: File f1 = new File(wEnv.getJkHome());
247: File f2 = new File(f1, "conf");
248:
249: if (!f2.exists()) {
250: log.error("No conf dir for ajp13.id " + f2);
251: return;
252: }
253:
254: File sf = new File(f2, "ajp13.id");
255:
256: if (log.isDebugEnabled())
257: log.debug("Using stop file: " + sf);
258:
259: try {
260: Properties props = new Properties();
261:
262: props.put("port", Integer.toString(portInt));
263: if (address != null) {
264: props.put("address", address.getHostAddress());
265: }
266: if (requiredSecret != null) {
267: props.put("secret", requiredSecret);
268: }
269:
270: FileOutputStream stopF = new FileOutputStream(sf);
271: props.save(stopF, "Automatically generated, don't edit");
272: } catch (IOException ex) {
273: log.debug("Can't create stop file: " + sf);
274: ex.printStackTrace();
275: }
276: }
277:
278: // -------------------- Incoming message --------------------
279: String requiredSecret = null;
280: int bodyNote;
281: int tmpBufNote;
282: int secretNote;
283:
284: boolean decoded = true;
285: boolean tomcatAuthentication = true;
286: boolean registerRequests = true;
287:
288: public int invoke(Msg msg, MsgContext ep) throws IOException {
289: int type = msg.getByte();
290: ThreadWithAttributes twa = null;
291: if (Thread.currentThread() instanceof ThreadWithAttributes) {
292: twa = (ThreadWithAttributes) Thread.currentThread();
293: }
294: Object control = ep.getControl();
295:
296: MessageBytes tmpMB = (MessageBytes) ep.getNote(tmpBufNote);
297: if (tmpMB == null) {
298: tmpMB = new MessageBytes();
299: ep.setNote(tmpBufNote, tmpMB);
300: }
301: if (log.isDebugEnabled())
302: log.debug("Handling " + type);
303:
304: switch (type) {
305: case JK_AJP13_FORWARD_REQUEST:
306: try {
307: if (twa != null) {
308: twa.setCurrentStage(control, "JkDecode");
309: }
310: decodeRequest(msg, ep, tmpMB);
311: if (twa != null) {
312: twa.setCurrentStage(control, "JkService");
313: twa.setParam(control, ((Request) ep.getRequest())
314: .unparsedURI());
315: }
316: } catch (Exception ex) {
317: log.error("Error decoding request ", ex);
318: msg.dump("Incomming message");
319: return ERROR;
320: }
321:
322: if (requiredSecret != null) {
323: String epSecret = (String) ep.getNote(secretNote);
324: if (epSecret == null
325: || !requiredSecret.equals(epSecret))
326: return ERROR;
327: }
328: /* XXX it should be computed from request, by workerEnv */
329: if (log.isDebugEnabled())
330: log.debug("Calling next " + next.getName() + " "
331: + next.getClass().getName());
332:
333: int err = next.invoke(msg, ep);
334: if (twa != null) {
335: twa.setCurrentStage(control, "JkDone");
336: }
337:
338: if (log.isDebugEnabled())
339: log.debug("Invoke returned " + err);
340: return err;
341: case JK_AJP13_SHUTDOWN:
342: String epSecret = null;
343: if (msg.getLen() > 3) {
344: // we have a secret
345: msg.getBytes(tmpMB);
346: epSecret = tmpMB.toString();
347: }
348:
349: if (requiredSecret != null
350: && requiredSecret.equals(epSecret)) {
351: if (log.isDebugEnabled())
352: log.debug("Received wrong secret, no shutdown ");
353: return ERROR;
354: }
355:
356: // XXX add isSameAddress check
357: JkChannel ch = ep.getSource();
358: if (!ch.isSameAddress(ep)) {
359: log.error("Shutdown request not from 'same address' ");
360: return ERROR;
361: }
362:
363: // forward to the default handler - it'll do the shutdown
364: next.invoke(msg, ep);
365:
366: log.info("Exiting");
367: System.exit(0);
368:
369: return OK;
370:
371: // We got a PING REQUEST, quickly respond with a PONG
372: case JK_AJP13_CPING_REQUEST:
373: msg.reset();
374: msg.appendByte(JK_AJP13_CPONG_REPLY);
375: ep.setType(JkHandler.HANDLE_SEND_PACKET);
376: ep.getSource().send(msg, ep);
377: return OK;
378:
379: case HANDLE_THREAD_END:
380: return OK;
381:
382: default:
383: log.info("Unknown message " + type);
384: }
385:
386: return OK;
387: }
388:
389: static int count = 0;
390:
391: private int decodeRequest(Msg msg, MsgContext ep, MessageBytes tmpMB)
392: throws IOException {
393: // FORWARD_REQUEST handler
394: Request req = (Request) ep.getRequest();
395: if (req == null) {
396: req = new Request();
397: Response res = new Response();
398: req.setResponse(res);
399: ep.setRequest(req);
400: if (registerRequests) {
401: ep.getSource().registerRequest(req, ep, count++);
402: }
403: }
404:
405: RequestInfo rp = req.getRequestProcessor();
406: rp.setStage(Constants.STAGE_PARSE);
407: MessageBytes tmpMB2 = (MessageBytes) req
408: .getNote(WorkerEnv.SSL_CERT_NOTE);
409: if (tmpMB2 != null) {
410: tmpMB2.recycle();
411: }
412: req.setStartTime(System.currentTimeMillis());
413: JkInputStream jkBody = (JkInputStream) ep.getNote(bodyNote);
414: if (jkBody == null) {
415: jkBody = new JkInputStream();
416: jkBody.setMsgContext(ep);
417:
418: ep.setNote(bodyNote, jkBody);
419: }
420:
421: jkBody.recycle();
422:
423: // Translate the HTTP method code to a String.
424: byte methodCode = msg.getByte();
425: if (methodCode != SC_M_JK_STORED) {
426: String mName = methodTransArray[(int) methodCode - 1];
427: req.method().setString(mName);
428: }
429:
430: msg.getBytes(req.protocol());
431: msg.getBytes(req.requestURI());
432:
433: msg.getBytes(req.remoteAddr());
434: msg.getBytes(req.remoteHost());
435: msg.getBytes(req.localName());
436: req.setLocalPort(msg.getInt());
437:
438: boolean isSSL = msg.getByte() != 0;
439: if (isSSL) {
440: // XXX req.setSecure( true );
441: req.scheme().setString("https");
442: }
443:
444: decodeHeaders(ep, msg, req, tmpMB);
445:
446: decodeAttributes(ep, msg, req, tmpMB);
447:
448: rp.setStage(Constants.STAGE_PREPARE);
449: MessageBytes valueMB = req.getMimeHeaders().getValue("host");
450: parseHost(valueMB, req);
451: // set cookies on request now that we have all headers
452: req.getCookies().setHeaders(req.getMimeHeaders());
453:
454: // Check to see if there should be a body packet coming along
455: // immediately after
456: int cl = req.getContentLength();
457: if (cl > 0) {
458: jkBody.setContentLength(cl);
459: jkBody.receive();
460: }
461:
462: if (log.isTraceEnabled()) {
463: log.trace(req.toString());
464: }
465:
466: return OK;
467: }
468:
469: private int decodeAttributes(MsgContext ep, Msg msg, Request req,
470: MessageBytes tmpMB) {
471: boolean moreAttr = true;
472:
473: while (moreAttr) {
474: byte attributeCode = msg.getByte();
475: if (attributeCode == SC_A_ARE_DONE)
476: return 200;
477:
478: /* Special case ( XXX in future API make it separate type !)
479: */
480: if (attributeCode == SC_A_SSL_KEY_SIZE) {
481: // Bug 1326: it's an Integer.
482: req.setAttribute(SSLSupport.KEY_SIZE_KEY, new Integer(
483: msg.getInt()));
484: //Integer.toString(msg.getInt()));
485: }
486:
487: if (attributeCode == SC_A_REQ_ATTRIBUTE) {
488: // 2 strings ???...
489: msg.getBytes(tmpMB);
490: String n = tmpMB.toString();
491: msg.getBytes(tmpMB);
492: String v = tmpMB.toString();
493: req.setAttribute(n, v);
494: }
495:
496: // 1 string attributes
497: switch (attributeCode) {
498: case SC_A_CONTEXT:
499: msg.getBytes(tmpMB);
500: // nothing
501: break;
502:
503: case SC_A_SERVLET_PATH:
504: msg.getBytes(tmpMB);
505: // nothing
506: break;
507:
508: case SC_A_REMOTE_USER:
509: if (tomcatAuthentication) {
510: // ignore server
511: msg.getBytes(tmpMB);
512: } else {
513: msg.getBytes(req.getRemoteUser());
514: }
515: break;
516:
517: case SC_A_AUTH_TYPE:
518: if (tomcatAuthentication) {
519: // ignore server
520: msg.getBytes(tmpMB);
521: } else {
522: msg.getBytes(req.getAuthType());
523: }
524: break;
525:
526: case SC_A_QUERY_STRING:
527: msg.getBytes(req.queryString());
528: break;
529:
530: case SC_A_JVM_ROUTE:
531: msg.getBytes(req.instanceId());
532: break;
533:
534: case SC_A_SSL_CERT:
535: req.scheme().setString("https");
536: // Transform the string into certificate.
537: MessageBytes tmpMB2 = (MessageBytes) req
538: .getNote(WorkerEnv.SSL_CERT_NOTE);
539: if (tmpMB2 == null) {
540: tmpMB2 = new MessageBytes();
541: req.setNote(WorkerEnv.SSL_CERT_NOTE, tmpMB2);
542: }
543: // SSL certificate extraction is costy, moved to JkCoyoteHandler
544: msg.getBytes(tmpMB2);
545: break;
546:
547: case SC_A_SSL_CIPHER:
548: req.scheme().setString("https");
549: msg.getBytes(tmpMB);
550: req.setAttribute(SSLSupport.CIPHER_SUITE_KEY, tmpMB
551: .toString());
552: break;
553:
554: case SC_A_SSL_SESSION:
555: req.scheme().setString("https");
556: msg.getBytes(tmpMB);
557: req.setAttribute(SSLSupport.SESSION_ID_KEY, tmpMB
558: .toString());
559: break;
560:
561: case SC_A_SECRET:
562: msg.getBytes(tmpMB);
563: String secret = tmpMB.toString();
564: log.info("Secret: " + secret);
565: // endpoint note
566: ep.setNote(secretNote, secret);
567: break;
568:
569: case SC_A_STORED_METHOD:
570: msg.getBytes(req.method());
571: break;
572:
573: default:
574: break; // ignore, we don't know about it - backward compat
575: }
576: }
577: return 200;
578: }
579:
580: private void decodeHeaders(MsgContext ep, Msg msg, Request req,
581: MessageBytes tmpMB) {
582: // Decode headers
583: MimeHeaders headers = req.getMimeHeaders();
584:
585: int hCount = msg.getInt();
586: for (int i = 0; i < hCount; i++) {
587: String hName = null;
588:
589: // Header names are encoded as either an integer code starting
590: // with 0xA0, or as a normal string (in which case the first
591: // two bytes are the length).
592: int isc = msg.peekInt();
593: int hId = isc & 0xFF;
594:
595: MessageBytes vMB = null;
596: isc &= 0xFF00;
597: if (0xA000 == isc) {
598: msg.getInt(); // To advance the read position
599: hName = headerTransArray[hId - 1];
600: vMB = headers.addValue(hName);
601: } else {
602: // reset hId -- if the header currently being read
603: // happens to be 7 or 8 bytes long, the code below
604: // will think it's the content-type header or the
605: // content-length header - SC_REQ_CONTENT_TYPE=7,
606: // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
607: // behaviour. see bug 5861 for more information.
608: hId = -1;
609: msg.getBytes(tmpMB);
610: ByteChunk bc = tmpMB.getByteChunk();
611: //hName=tmpMB.toString();
612: // vMB=headers.addValue( hName );
613: vMB = headers.addValue(bc.getBuffer(), bc.getStart(),
614: bc.getLength());
615: }
616:
617: msg.getBytes(vMB);
618:
619: if (hId == SC_REQ_CONTENT_LENGTH
620: || tmpMB.equalsIgnoreCase("Content-Length")) {
621: // just read the content-length header, so set it
622: int contentLength = (vMB == null) ? -1 : vMB.getInt();
623: req.setContentLength(contentLength);
624: } else if (hId == SC_REQ_CONTENT_TYPE
625: || tmpMB.equalsIgnoreCase("Content-Type")) {
626: // just read the content-type header, so set it
627: ByteChunk bchunk = vMB.getByteChunk();
628: req.contentType().setBytes(bchunk.getBytes(),
629: bchunk.getOffset(), bchunk.getLength());
630: }
631: }
632: }
633:
634: /**
635: * Parse host.
636: */
637: private void parseHost(MessageBytes valueMB, Request request)
638: throws IOException {
639:
640: if (valueMB == null || valueMB.isNull()) {
641: // HTTP/1.0
642: // Default is what the socket tells us. Overriden if a host is
643: // found/parsed
644: request.setServerPort(request.getLocalPort());
645: request.serverName().duplicate(request.localName());
646: return;
647: }
648:
649: ByteChunk valueBC = valueMB.getByteChunk();
650: byte[] valueB = valueBC.getBytes();
651: int valueL = valueBC.getLength();
652: int valueS = valueBC.getStart();
653: int colonPos = -1;
654: CharChunk hostNameC = (CharChunk) request.getNote(HOSTBUFFER);
655: if (hostNameC == null) {
656: hostNameC = new CharChunk(valueL);
657: request.setNote(HOSTBUFFER, hostNameC);
658: }
659: hostNameC.recycle();
660:
661: boolean ipv6 = (valueB[valueS] == '[');
662: boolean bracketClosed = false;
663: for (int i = 0; i < valueL; i++) {
664: char b = (char) valueB[i + valueS];
665: hostNameC.append(b);
666: if (b == ']') {
667: bracketClosed = true;
668: } else if (b == ':') {
669: if (!ipv6 || bracketClosed) {
670: colonPos = i;
671: break;
672: }
673: }
674: }
675:
676: if (colonPos < 0) {
677: if (request.scheme().equalsIgnoreCase("https")) {
678: // 80 - Default HTTTP port
679: request.setServerPort(443);
680: } else {
681: // 443 - Default HTTPS port
682: request.setServerPort(80);
683: }
684: request.serverName().setChars(hostNameC.getChars(),
685: hostNameC.getStart(), hostNameC.getLength());
686: } else {
687:
688: request.serverName().setChars(hostNameC.getChars(),
689: hostNameC.getStart(), colonPos);
690:
691: int port = 0;
692: int mult = 1;
693: for (int i = valueL - 1; i > colonPos; i--) {
694: int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
695: if (charValue == -1) {
696: // Invalid character
697: throw new CharConversionException(
698: "Invalid char in port: "
699: + valueB[i + valueS]);
700: }
701: port = port + (charValue * mult);
702: mult = 10 * mult;
703: }
704: request.setServerPort(port);
705:
706: }
707:
708: }
709:
710: }
|