public void handleIAC()
		throws IOException, InterruptedIOException
	{
		if((in==null)||(out==null))
			return;
		lastIACIn=System.currentTimeMillis();
		int c=readByte();
		if(c>255)
			c=c&0xff;

		switch(c)
		{
		case TELNET_IAC:
			bNextByteIs255=true;
			break;
		case TELNET_SB:
		{
			CharArrayWriter subOptionStream=new CharArrayWriter();
			final int subOptionCode = readByte();
			int last = 0;
			if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
				Log.debugOut("Reading sub-option "+subOptionCode);
			while(((last = readByte()) != -1)
			&&(!killFlag))
			{
				if(subOptionStream.size()>1024*1024*5)
				{
					killFlag=true;
					return;
				}
				else
				if (last == TELNET_IAC)
				{
					last = readByte();
					if (last == TELNET_IAC)
						subOptionStream.write(TELNET_IAC);
					else
					if (last == TELNET_SE)
						break;
				}
				else
					subOptionStream.write((char)last);
			}
			final char[] subOptionData=subOptionStream.toCharArray();
			subOptionStream=null;
			handleSubOption(subOptionCode, subOptionData, subOptionData.length);
			break;
		}
		case TELNET_DO:
		{
			final int last=readByte();
			setClientTelnetMode(last,true);
			if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
				Log.debugOut("Got DO "+Session.TELNET_DESCS[last]);
			if((terminalType.equalsIgnoreCase("zmud")||terminalType.equalsIgnoreCase("cmud"))&&(last==Session.TELNET_ECHO))
				setClientTelnetMode(Session.TELNET_ECHO,false);
			if(last==TELNET_TERMTYPE)
				negotiateTelnetMode(rawout,TELNET_TERMTYPE);
			if((last==TELNET_COMPRESS2)&&(getServerTelnetMode(last)))
			{
				setClientTelnetMode(last,true);
				if(connectionComplete)
				{
					prompt(new TickingCallback(250)
					{
						@Override
						public boolean tick(int counter)
						{
							try
							{
								if((out==null)||(killFlag))
									return false;
								out.flush();
								rawout.flush();
								switch(counter)
								{
								case 3:
								{
									if(getClientTelnetMode(TELNET_COMPRESS2))
									{
										negotiateTelnetMode(rawout,TELNET_COMPRESS2);
										rawout.flush();
										final ZOutputStream zOut=new ZOutputStream(rawout, JZlib.Z_DEFAULT_COMPRESSION);
										rawout=zOut;
										zOut.setFlushMode(JZlib.Z_SYNC_FLUSH);
										out = new PrintWriter(new OutputStreamWriter(zOut,CMProps.getVar(CMProps.Str.CHARSETOUTPUT)));
										if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
											Log.debugOut("MCCP compression started");
									}
									break;
								}
								case 10:
									return false;
								default:
									break;
								}
								return true;
							}
							catch(final IOException e)
							{
								if(e.getMessage()==null)
									Log.errOut(e);
								else
									Log.errOut(e.getMessage());
							}
							return false;
						}
					});
				}
			}
			else
			if(!mightSupportTelnetMode(last))
				changeTelnetMode(last,false);
			else
			if(!getServerTelnetMode(last))
				changeTelnetMode(last,true);
			if(serverTelnetCodes[TELNET_LOGOUT])
				setKillFlag(true);
			break;
		}
		case TELNET_DONT:
		{
			final int last=readByte();
			if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
				Log.debugOut("Got DONT "+Session.TELNET_DESCS[last]);
			setClientTelnetMode(last,false);
			if((last==TELNET_COMPRESS2)&&(getServerTelnetMode(last)))
			{
				setClientTelnetMode(last,false);
				rawout=new BufferedOutputStream(sock[0].getOutputStream());
				out = new PrintWriter(new OutputStreamWriter(rawout,CMProps.getVar(CMProps.Str.CHARSETOUTPUT)));
			}
			if((mightSupportTelnetMode(last)&&(getServerTelnetMode(last))))
				changeTelnetMode(last,false);
			break;
		}
		case TELNET_WILL:
		{
			final int last=readByte();
			if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
				Log.debugOut("Got WILL "+Session.TELNET_DESCS[last]);
			setClientTelnetMode(last,true);
			if((terminalType.equalsIgnoreCase("zmud")||terminalType.equalsIgnoreCase("cmud"))&&(last==Session.TELNET_ECHO))
				setClientTelnetMode(Session.TELNET_ECHO,false);
			if(!mightSupportTelnetMode(last))
				changeTelnetModeBackwards(last,false);
			else
			if(!getServerTelnetMode(last))
				changeTelnetModeBackwards(last,true);
			if(serverTelnetCodes[TELNET_LOGOUT])
				setKillFlag(true);
			break;
		}
		case TELNET_WONT:
		{
			final int last=readByte();
			if(CMSecurity.isDebugging(CMSecurity.DbgFlag.TELNET))
				Log.debugOut("Got WONT "+Session.TELNET_DESCS[last]);
			setClientTelnetMode(last,false);
			if((mightSupportTelnetMode(last))&&(getServerTelnetMode(last)))
				changeTelnetModeBackwards(last,false);
			break;
		}
		case TELNET_AYT:
			rawCharsOut(" \b");
			break;
		default:
			return;
		}
	}