/* Copyright (C) 2011 monte This file is part of PSP NetParty. PSP NetParty is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package pspnetparty.client.swt; import java.io.File; import java.io.IOException; import java.net.BindException; import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map.Entry; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.PreferenceNode; import org.eclipse.jface.resource.ColorRegistry; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import pspnetparty.client.swt.PlayClient.PortalQuery; import pspnetparty.client.swt.config.MiscSettingPage; import pspnetparty.client.swt.config.ChatTextPresetsPage; import pspnetparty.client.swt.config.IPreferenceNodeProvider; import pspnetparty.client.swt.config.IniAppData; import pspnetparty.client.swt.config.IniChatTextPresets; import pspnetparty.client.swt.config.IniSettings; import pspnetparty.client.swt.config.IniUserProfile; import pspnetparty.client.swt.message.AdminNotify; import pspnetparty.client.swt.message.Chat; import pspnetparty.client.swt.message.ErrorLog; import pspnetparty.client.swt.message.InfoLog; import pspnetparty.client.swt.message.LogViewer; import pspnetparty.client.swt.message.RoomLog; import pspnetparty.client.swt.message.ServerLog; import pspnetparty.lib.IniFile; import pspnetparty.lib.IniSection; import pspnetparty.lib.LobbyUserState; import pspnetparty.lib.Utility; import pspnetparty.lib.constants.AppConstants; import pspnetparty.lib.constants.ProtocolConstants; import pspnetparty.lib.engine.IMyRoomMasterHandler; import pspnetparty.lib.engine.MyRoomEngine; import pspnetparty.lib.engine.PlayRoom; import pspnetparty.lib.socket.IProtocol; import pspnetparty.lib.socket.IProtocolDriver; import pspnetparty.lib.socket.IProtocolMessageHandler; import pspnetparty.lib.socket.ISocketConnection; import pspnetparty.lib.socket.PacketData; import pspnetparty.lib.socket.TextProtocolDriver; import pspnetparty.lib.socket.TransportLayer; import pspnetparty.wlan.WlanDevice; import pspnetparty.wlan.WlanLibrary; import pspnetparty.wlan.WlanNetwork; public class RoomWindow implements IAppWindow { private static final String SECTION_LAN_ADAPTERS = "LanAdapters"; private static final int MAX_SERVER_HISTORY = 10; private static final int DEFAULT_MAX_PLAYERS = 4; private static final String INI_ROOM_TITLE = "Title"; private static final String INI_ROOM_PASSWORD = "Password"; private static final String INI_ROOM_CAPACITY = "Capacity"; private static final String INI_ROOM_DESCRIPTION = "Description"; private static final String INI_ROOM_REMARKS = "Remarks"; enum SessionState { OFFLINE, MY_ROOM_MASTER, CONNECTING_ROOM_PARTICIPANT, ROOM_PARTICIPANT, CONNECTING_ROOM_MASTER, ROOM_MASTER, NEGOTIATING, }; private PlayClient application; private IniChatTextPresets chatTextPresets; private Shell shell; private boolean isActiveWindow; private SessionState sessionState; private String roomLoginName; private String roomMasterName; private String roomServerAddressPort; private MyRoomEngine myRoomEngine; private RoomProtocol roomProtocol = new RoomProtocol(); private ISocketConnection roomConnection = ISocketConnection.NULL; private TunnelProtocol tunnelProtocol = new TunnelProtocol(); private ISocketConnection tunnelConnection = ISocketConnection.NULL; private MyRoomEntryProtocol myRoomEntryProtocol = new MyRoomEntryProtocol(); private ISocketConnection myRoomEntryConnection = ISocketConnection.NULL; private int scanIntervalMillis = 2000; private long nextSsidCheckTime = 0L; private boolean tunnelIsLinked = false; private boolean isPacketCapturing = false; private boolean isSSIDScaning = false; private boolean isRoomInfoUpdating = false; private WlanLibrary currentWlanLibrary; private WlanDevice currentWlanDevice = WlanDevice.NULL; private ByteBuffer bufferForCapturing = ByteBuffer.allocateDirect(WlanDevice.CAPTURE_BUFFER_SIZE); private ArrayList<WlanDevice> wlanAdapterList = new ArrayList<WlanDevice>(); private HashMap<WlanDevice, String> wlanAdapterMacAddressMap = new HashMap<WlanDevice, String>(); private HashMap<String, Player> roomPlayerMap = new LinkedHashMap<String, Player>(); private HashMap<String, TraficStatistics> traficStatsMap = new HashMap<String, TraficStatistics>(); public int actualSentBytes; public int actualRecievedBytes; private Thread packetMonitorThread; private Thread packetCaptureThread; private Thread wlanScannerThread; private Widgets widgets; private ComboHistoryManager roomServerHistoryManager; private ComboHistoryManager roomAddressHistoryManager; public RoomWindow(PlayClient application) { this.application = application; shell = new Shell(SwtUtils.DISPLAY); shell.setText("ルーム - " + AppConstants.APP_NAME); chatTextPresets = new IniChatTextPresets(application.getIniSection(IniChatTextPresets.SECTION_NAME)); myRoomEngine = new MyRoomEngine(new MyRoomServerHandler()); widgets = new Widgets(); widgets.initWidgets(); IniSettings iniSettings = application.getSettings(); IniAppData iniAppData = application.getAppData(); widgets.formMyRoomModePortSpinner.setSelection(iniSettings.getMyRoomPort()); widgets.formMyRoomModeHostText.setText(iniSettings.getMyRoomHostName()); widgets.initWidgetListeners(); widgets.initMenus(); changeStateTo(SessionState.OFFLINE); shell.setMinimumSize(new Point(650, 400)); iniAppData.restoreMainWindow(shell); String[] stringList; stringList = iniSettings.getRoomServerList(); ComboHistoryManager.addList(widgets.formManualModeRoomServerCombo, stringList); stringList = iniAppData.getRoomServerHistory(); roomServerHistoryManager = new ComboHistoryManager(widgets.formManualModeRoomServerCombo, stringList, MAX_SERVER_HISTORY, true); stringList = iniSettings.getRoomAddressList(); ComboHistoryManager.addList(widgets.formManualModeRoomAddressCombo, stringList); stringList = iniAppData.getRoomAddressHistory(); roomAddressHistoryManager = new ComboHistoryManager(widgets.formManualModeRoomAddressCombo, stringList, MAX_SERVER_HISTORY, true); application.addConfigPageProvider(new IPreferenceNodeProvider() { @Override public PreferenceNode createPreferenceNode() { return new PreferenceNode("chatpresets", new ChatTextPresetsPage(RoomWindow.this.application.getSettings(), chatTextPresets)); } }); currentWlanLibrary = iniSettings.getWlanLibrary(); refreshLanAdapterList(); initBackgroundThreads(); } public Shell getShell() { return shell; } private class Widgets { private Composite toolBarContainer; private SashForm mainSashForm; private Composite formModeSwitchContainer; private StackLayout roomModeStackLayout; private Combo formModeSelectionCombo; private Composite formAutoModeContainer; private Text formAutoModeServerAddress; private Button formAutoModeRoomButton; private Composite formManualModeContainer; private Combo formManualModeRoomServerCombo; private Button formManualModeRoomServerButton; private Combo formManualModeRoomAddressCombo; private Button formManualModeRoomAddressButton; private Composite formMyRoomModeContainer; private Text formMyRoomModeHostText; private Spinner formMyRoomModePortSpinner; private Button formMyRoomModeStartButton; private Text formMyRoomModeRoomServer; private Button formMyRoomModeEntryButton; private Text formMasterNameText; private Text formTitleText; private Text formPasswordText; private Spinner formMaxPlayersSpiner; private Text formTimestampText; private Text formDescriptionText; private Text formRemarksText; private Button formEditSaveButton; private Button formEditLoadButton; private Button formEditSubmitButton; private SashForm centerSashForm; private Combo wlanAdapterListCombo; private Button wlanPspCommunicationButton; private TableViewer packetMonitorTable; private LogViewer logViewer; private Text chatText; private Button multilineChatButton; private SashForm rightSashForm; private Button ssidStartScan; private Text ssidCurrentSsidText; private Label ssidMatchLabel; private Text ssidMatchText; private Spinner ssidScanIntervalSpinner; private Button ssidAutoDetectCheck; private TableViewer ssidListTableViewer; private TableViewer roomPlayerListTable; private Button macFilteringWhiteListCheck; private List macFilteringWhiteList; private Button macFilteringBlackListCheck; private List macFilteringBlackList; private Composite statusBarContainer; private Label statusUserNameLabel; private Label statusServerAddressLabel; private Label statusTunnelConnectionLabel; private Label statusTraficStatusLabel; private MenuItem playerMenuChaseSsid; private MenuItem playerMenuSetSsid; private MenuItem playerMenuCopySsid; private MenuItem playerMenuKick; private MenuItem playerMenuMasterTransfer; private MenuItem statusServerAddressMenuCopy; private MenuItem packetMonitorMenuCopy; private MenuItem packetMonitorMenuWhiteList; private MenuItem packetMonitorMenuBlackList; private MenuItem packetMonitorMenuClear; private MenuItem macFilteringWhiteListMenuRemove; private MenuItem macFilteringBlackListMenuRemove; private Menu statusTunnelConnectionMenu; private MenuItem statusTunnelConnectionMenuChangeTransport; private Composite chatPresetContainer; private Button chatTextPresetF1; private Button chatTextPresetF2; private Button chatTextPresetF3; private Button chatTextPresetF4; private Button chatTextPresetF5; private Button chatTextPresetF6; private Button chatTextPresetF7; private Button chatTextPresetF8; private Button chatTextPresetF9; private Button chatTextPresetF10; private Button chatTextPresetF11; private Button chatTextPresetF12; private void initWidgets() { IniAppData iniAppData = application.getAppData(); try { shell.setImages(application.getShellImages()); } catch (RuntimeException e) { e.printStackTrace(); } GridLayout gridLayout; GridData gridData; // ImageRegistry imageRegistry = application.getImageRegistry(); ColorRegistry colorRegistry = application.getColorRegistry(); gridLayout = new GridLayout(1, false); gridLayout.horizontalSpacing = 3; gridLayout.verticalSpacing = 0; gridLayout.marginWidth = 2; gridLayout.marginHeight = 1; shell.setLayout(gridLayout); toolBarContainer = new Composite(shell, SWT.NONE); toolBarContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); toolBarContainer.setLayout(new FillLayout()); application.createToolBar(toolBarContainer, RoomWindow.this); mainSashForm = new SashForm(shell, SWT.HORIZONTAL); gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.verticalIndent = 3; mainSashForm.setLayoutData(gridData); Composite leftContainer = new Composite(mainSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 1; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; leftContainer.setLayout(gridLayout); Composite formModeContainer = new Composite(leftContainer, SWT.NONE); gridLayout = new GridLayout(2, false); gridLayout.horizontalSpacing = 8; gridLayout.verticalSpacing = 3; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.marginLeft = 3; formModeContainer.setLayout(gridLayout); formModeContainer.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false)); Label formModeSelectionLabel = new Label(formModeContainer, SWT.NONE); formModeSelectionLabel.setText("モード"); formModeSelectionLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formModeSelectionLabel); formModeSelectionCombo = new Combo(formModeContainer, SWT.READ_ONLY); formModeSelectionCombo.setItems(new String[] { "オート", "マニュアル", "マイルーム" }); formModeSelectionCombo.select(0); formModeSelectionCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formModeSelectionCombo); formModeSwitchContainer = new Composite(formModeContainer, SWT.NONE); roomModeStackLayout = new StackLayout(); formModeSwitchContainer.setLayout(roomModeStackLayout); formModeSwitchContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); formAutoModeContainer = new Composite(formModeSwitchContainer, SWT.NONE); gridLayout = new GridLayout(2, false); gridLayout.horizontalSpacing = 8; gridLayout.verticalSpacing = 6; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.marginTop = 2; formAutoModeContainer.setLayout(gridLayout); Label formAutoModeServerAddressLabel = new Label(formAutoModeContainer, SWT.NONE); formAutoModeServerAddressLabel.setText("サーバー"); application.initControl(formAutoModeServerAddressLabel); formAutoModeServerAddress = new Text(formAutoModeContainer, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY); formAutoModeServerAddress.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formAutoModeServerAddress); formAutoModeRoomButton = new Button(formAutoModeContainer, SWT.PUSH); formAutoModeRoomButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, true, 2, 1)); application.initControl(formAutoModeRoomButton); formManualModeContainer = new Composite(formModeSwitchContainer, SWT.NONE); gridLayout = new GridLayout(3, false); gridLayout.horizontalSpacing = 5; gridLayout.verticalSpacing = 4; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; formManualModeContainer.setLayout(gridLayout); Label formManualModeServerLabel = new Label(formManualModeContainer, SWT.NONE); formManualModeServerLabel.setText("サーバー"); application.initControl(formManualModeServerLabel); formManualModeRoomServerCombo = new Combo(formManualModeContainer, SWT.NONE); formManualModeRoomServerCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formManualModeRoomServerCombo); formManualModeRoomServerButton = new Button(formManualModeContainer, SWT.PUSH); formManualModeRoomServerButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); application.initControl(formManualModeRoomServerButton); Label formManualModeAddressLabel = new Label(formManualModeContainer, SWT.NONE); formManualModeAddressLabel.setText("アドレス"); application.initControl(formManualModeAddressLabel); formManualModeRoomAddressCombo = new Combo(formManualModeContainer, SWT.NONE); formManualModeRoomAddressCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formManualModeRoomAddressCombo); formManualModeRoomAddressButton = new Button(formManualModeContainer, SWT.PUSH); formManualModeRoomAddressButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); application.initControl(formManualModeRoomAddressButton); formMyRoomModeContainer = new Composite(formModeSwitchContainer, SWT.NONE); gridLayout = new GridLayout(4, false); gridLayout.horizontalSpacing = 3; gridLayout.verticalSpacing = 4; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.marginRight = 1; formMyRoomModeContainer.setLayout(gridLayout); Label formServerModeEntryLabel = new Label(formMyRoomModeContainer, SWT.NONE); formServerModeEntryLabel.setText("ホスト:ポート"); formServerModeEntryLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formServerModeEntryLabel); formMyRoomModeHostText = new Text(formMyRoomModeContainer, SWT.SINGLE | SWT.BORDER); formMyRoomModeHostText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); application.initControl(formMyRoomModeHostText); formMyRoomModePortSpinner = new Spinner(formMyRoomModeContainer, SWT.BORDER); formMyRoomModePortSpinner.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); formMyRoomModePortSpinner.setMinimum(1); formMyRoomModePortSpinner.setMaximum(65535); formMyRoomModePortSpinner.setSelection(30000); application.initControl(formMyRoomModePortSpinner); formMyRoomModeStartButton = new Button(formMyRoomModeContainer, SWT.PUSH); formMyRoomModeStartButton.setText("起動する"); formMyRoomModeStartButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); application.initControl(formMyRoomModeStartButton); Label formMyRoomModeAddressLabel = new Label(formMyRoomModeContainer, SWT.NONE); formMyRoomModeAddressLabel.setText("サーバー"); formMyRoomModeAddressLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formMyRoomModeAddressLabel); formMyRoomModeRoomServer = new Text(formMyRoomModeContainer, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY); formMyRoomModeRoomServer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); application.initControl(formMyRoomModeRoomServer); formMyRoomModeEntryButton = new Button(formMyRoomModeContainer, SWT.PUSH); formMyRoomModeEntryButton.setText("検索登録"); formMyRoomModeEntryButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); application.initControl(formMyRoomModeEntryButton); roomModeStackLayout.topControl = formAutoModeContainer; Group formEditGroup = new Group(leftContainer, SWT.NONE); formEditGroup.setText("部屋情報"); formEditGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); gridLayout = new GridLayout(2, false); gridLayout.marginWidth = 3; gridLayout.marginHeight = 3; formEditGroup.setLayout(gridLayout); Label formMasterNameLabel = new Label(formEditGroup, SWT.NONE); formMasterNameLabel.setText("部屋主"); formMasterNameLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formMasterNameLabel); formMasterNameText = new Text(formEditGroup, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); formMasterNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formMasterNameText); Label formTitleLabel = new Label(formEditGroup, SWT.NONE); formTitleLabel.setText("部屋名"); formTitleLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formTitleLabel); formTitleText = new Text(formEditGroup, SWT.SINGLE | SWT.BORDER); formTitleText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); formTitleText.setTextLimit(100); application.initControl(formTitleText); Label formPasswordLabel = new Label(formEditGroup, SWT.NONE); formPasswordLabel.setText("パスワード"); formPasswordLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formPasswordLabel); formPasswordText = new Text(formEditGroup, SWT.SINGLE | SWT.BORDER); formPasswordText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); formPasswordText.setTextLimit(30); application.initControl(formPasswordText); Label formMaxPlayersLabel = new Label(formEditGroup, SWT.NONE); formMaxPlayersLabel.setText("定員"); formMaxPlayersLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formMaxPlayersLabel); Composite formMaxPlayerContainer = new Composite(formEditGroup, SWT.NONE); formMaxPlayerContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); gridLayout = new GridLayout(3, false); gridLayout.horizontalSpacing = 3; gridLayout.verticalSpacing = 0; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; formMaxPlayerContainer.setLayout(gridLayout); formMaxPlayersSpiner = new Spinner(formMaxPlayerContainer, SWT.READ_ONLY | SWT.BORDER); formMaxPlayersSpiner.setMinimum(2); formMaxPlayersSpiner.setMaximum(ProtocolConstants.Room.MAX_ROOM_PLAYERS); formMaxPlayersSpiner.setSelection(DEFAULT_MAX_PLAYERS); application.initControl(formMaxPlayersSpiner); Label formTimestampLabel = new Label(formMaxPlayerContainer, SWT.NONE); formTimestampLabel.setText("作成日時"); formTimestampLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(formTimestampLabel); formTimestampText = new Text(formMaxPlayerContainer, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); formTimestampText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(formTimestampText); SashForm formDescriptionSashForm = new SashForm(formEditGroup, SWT.VERTICAL); gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); gridData.verticalIndent = 1; formDescriptionSashForm.setLayoutData(gridData); Composite formDescriptionContainer = new Composite(formDescriptionSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.marginTop = 4; gridLayout.verticalSpacing = 2; formDescriptionContainer.setLayout(gridLayout); Label formDescriptionLabel = new Label(formDescriptionContainer, SWT.NONE); formDescriptionLabel.setText("部屋の紹介 (検索に表示されます)"); gridData = new GridData(); gridData.horizontalIndent = 3; formDescriptionLabel.setLayoutData(gridData); application.initControl(formDescriptionLabel); formDescriptionText = new Text(formDescriptionContainer, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP); formDescriptionText.setTextLimit(1000); formDescriptionText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); application.initControl(formDescriptionText); Composite formRemarksContainer = new Composite(formDescriptionSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.marginTop = 4; gridLayout.verticalSpacing = 2; formRemarksContainer.setLayout(gridLayout); Label formRemarksLabel = new Label(formRemarksContainer, SWT.NONE); formRemarksLabel.setText("備考 (検索に表示されません)"); gridData = new GridData(); gridData.horizontalIndent = 3; formRemarksLabel.setLayoutData(gridData); application.initControl(formRemarksLabel); formRemarksText = new Text(formRemarksContainer, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP); formRemarksText.setTextLimit(1000); formRemarksText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); application.initControl(formRemarksText); Composite formEditControlContainer = new Composite(formEditGroup, SWT.NONE); formEditControlContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); gridLayout = new GridLayout(3, false); gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.verticalSpacing = 0; formEditControlContainer.setLayout(gridLayout); formEditSaveButton = new Button(formEditControlContainer, SWT.PUSH); formEditSaveButton.setText("保存する"); formEditSaveButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); application.initControl(formEditSaveButton); formEditLoadButton = new Button(formEditControlContainer, SWT.PUSH); formEditLoadButton.setText("読み込む"); formEditLoadButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); application.initControl(formEditLoadButton); formEditSubmitButton = new Button(formEditControlContainer, SWT.PUSH); formEditSubmitButton.setText("部屋情報を更新"); formEditSubmitButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false)); application.initControl(formEditSubmitButton); centerSashForm = new SashForm(mainSashForm, SWT.VERTICAL); centerSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Composite centerUpperContainer = new Composite(centerSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.verticalSpacing = 3; gridLayout.horizontalSpacing = 0; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; centerUpperContainer.setLayout(gridLayout); Composite wlanAdaptorContainer = new Composite(centerUpperContainer, SWT.NONE); gridLayout = new GridLayout(3, false); gridLayout.verticalSpacing = 0; gridLayout.horizontalSpacing = 3; gridLayout.marginHeight = 0; gridLayout.marginWidth = 2; wlanAdaptorContainer.setLayout(gridLayout); wlanAdaptorContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); Label wlanAdapterListLabel = new Label(wlanAdaptorContainer, SWT.NONE); wlanAdapterListLabel.setText("無線LANアダプタ"); application.initControl(wlanAdapterListLabel); wlanAdapterListCombo = new Combo(wlanAdaptorContainer, SWT.READ_ONLY); wlanAdapterListCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(wlanAdapterListCombo); wlanPspCommunicationButton = new Button(wlanAdaptorContainer, SWT.TOGGLE); wlanPspCommunicationButton.setText("PSPと通信開始"); application.initControl(wlanPspCommunicationButton); packetMonitorTable = new TableViewer(centerUpperContainer, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); packetMonitorTable.getTable().setHeaderVisible(true); packetMonitorTable.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); application.initControl(packetMonitorTable.getTable()); TableColumn packetMonitorIsMineColumn = new TableColumn(packetMonitorTable.getTable(), SWT.CENTER); packetMonitorIsMineColumn.setText(""); SwtUtils.installSorter(packetMonitorTable, packetMonitorIsMineColumn, TraficStatistics.MINE_SORTER); TableColumn packetMonitorMacAddressColumn = new TableColumn(packetMonitorTable.getTable(), SWT.LEFT); packetMonitorMacAddressColumn.setText("MACアドレス"); SwtUtils.installSorter(packetMonitorTable, packetMonitorMacAddressColumn, TraficStatistics.MAC_ADDRESS_SORTER); TableColumn packetMonitorPlayerNameColumn = new TableColumn(packetMonitorTable.getTable(), SWT.LEFT); packetMonitorPlayerNameColumn.setText("ユーザー名"); SwtUtils.installSorter(packetMonitorTable, packetMonitorPlayerNameColumn, TraficStatistics.PLAYER_NAME_SORTER); TableColumn packetMonitorInSpeedColumn = new TableColumn(packetMonitorTable.getTable(), SWT.RIGHT); packetMonitorInSpeedColumn.setText("In (Kbps)"); SwtUtils.installSorter(packetMonitorTable, packetMonitorInSpeedColumn, TraficStatistics.IN_SPEED_SORTER); TableColumn packetMonitorOutSpeedColumn = new TableColumn(packetMonitorTable.getTable(), SWT.RIGHT); packetMonitorOutSpeedColumn.setText("Out (Kbps)"); SwtUtils.installSorter(packetMonitorTable, packetMonitorOutSpeedColumn, TraficStatistics.OUT_SPEED_SORTER); TableColumn packetMonitorTotalInBytesColumn = new TableColumn(packetMonitorTable.getTable(), SWT.RIGHT); packetMonitorTotalInBytesColumn.setText("In 累積バイト"); SwtUtils.installSorter(packetMonitorTable, packetMonitorTotalInBytesColumn, TraficStatistics.TOTAL_IN_SORTER); TableColumn packetMonitorTotalOutBytesColumn = new TableColumn(packetMonitorTable.getTable(), SWT.RIGHT); packetMonitorTotalOutBytesColumn.setText("Out 累積バイト"); SwtUtils.installSorter(packetMonitorTable, packetMonitorTotalOutBytesColumn, TraficStatistics.TOTAL_OUT_SORTER); packetMonitorTable.setContentProvider(new TraficStatistics.ContentProvider()); packetMonitorTable.setLabelProvider(new TraficStatistics.LabelProvider()); SwtUtils.enableColumnDrag(packetMonitorTable.getTable()); Composite chatContainer = new Composite(centerSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.verticalSpacing = 0; gridLayout.horizontalSpacing = 0; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; chatContainer.setLayout(gridLayout); logViewer = new LogViewer(chatContainer, application.getSettings().getMaxLogCount(), application); logViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); chatPresetContainer = new Composite(chatContainer, SWT.NONE); gridLayout = new GridLayout(12, false); gridLayout.verticalSpacing = 0; gridLayout.horizontalSpacing = 3; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.marginTop = 3; gridLayout.marginBottom = 1; gridLayout.marginRight = 1; chatPresetContainer.setLayout(gridLayout); gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); chatPresetContainer.setLayoutData(gridData); chatTextPresetF1 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF2 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF3 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF4 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF5 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF6 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF7 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF8 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF9 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF10 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF11 = new Button(chatPresetContainer, SWT.PUSH); chatTextPresetF12 = new Button(chatPresetContainer, SWT.PUSH); updateChatPresetButtons(); Composite chatCommandContainer = new Composite(chatContainer, SWT.NONE); gridLayout = new GridLayout(2, false); gridLayout.verticalSpacing = 0; gridLayout.horizontalSpacing = 3; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.marginTop = 3; gridLayout.marginBottom = 1; gridLayout.marginRight = 1; chatCommandContainer.setLayout(gridLayout); chatCommandContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); chatText = new Text(chatCommandContainer, SWT.BORDER | SWT.SINGLE); chatText.setTextLimit(300); chatText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initChatControl(chatText); multilineChatButton = new Button(chatCommandContainer, SWT.PUSH); multilineChatButton.setText("複数行"); application.initControl(multilineChatButton); rightSashForm = new SashForm(mainSashForm, SWT.VERTICAL); Composite ssidContainer = new Composite(rightSashForm, SWT.NONE); gridLayout = new GridLayout(2, false); gridLayout.horizontalSpacing = 1; gridLayout.verticalSpacing = 4; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; ssidContainer.setLayout(gridLayout); Label ssidCurrentSsidLabel = new Label(ssidContainer, SWT.NONE); ssidCurrentSsidLabel.setText("現在のSSID"); ssidCurrentSsidLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(ssidCurrentSsidLabel); ssidCurrentSsidText = new Text(ssidContainer, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); ssidCurrentSsidText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(ssidCurrentSsidText); ssidMatchLabel = new Label(ssidContainer, SWT.NONE); ssidMatchLabel.setText("絞り込み"); ssidMatchLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(ssidMatchLabel); ssidMatchText = new Text(ssidContainer, SWT.SINGLE | SWT.BORDER); ssidMatchText.setText("PSP_"); ssidMatchText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); application.initControl(ssidMatchText); Composite ssidControlContainer = new Composite(ssidContainer, SWT.NONE); ssidControlContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); gridLayout = new GridLayout(4, false); gridLayout.horizontalSpacing = 3; gridLayout.verticalSpacing = 0; gridLayout.marginWidth = 1; gridLayout.marginHeight = 0; ssidControlContainer.setLayout(gridLayout); ssidStartScan = new Button(ssidControlContainer, SWT.TOGGLE); ssidStartScan.setText("スキャン開始"); ssidStartScan.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); ssidStartScan.setEnabled(false); application.initControl(ssidStartScan); ssidScanIntervalSpinner = new Spinner(ssidControlContainer, SWT.BORDER); ssidScanIntervalSpinner.setMinimum(500); ssidScanIntervalSpinner.setMaximum(9999); ssidScanIntervalSpinner.setSelection(scanIntervalMillis); application.initControl(ssidScanIntervalSpinner); Label ssidScanIntervalLabel = new Label(ssidControlContainer, SWT.NONE); ssidScanIntervalLabel.setText("ミリ秒"); application.initControl(ssidScanIntervalLabel); ssidAutoDetectCheck = new Button(ssidControlContainer, SWT.CHECK | SWT.FLAT); ssidAutoDetectCheck.setText("自動追尾"); ssidAutoDetectCheck.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); application.initControl(ssidAutoDetectCheck); ssidListTableViewer = new TableViewer(ssidContainer, SWT.BORDER | SWT.FULL_SELECTION); ssidListTableViewer.setContentProvider(new ArrayContentProvider()); ssidListTableViewer.setLabelProvider(new WlanUtils.LabelProvider()); Table ssidListTable = ssidListTableViewer.getTable(); ssidListTable.setHeaderVisible(true); ssidListTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); application.initControl(ssidListTable); TableColumn ssidListTableSsidColumn = new TableColumn(ssidListTable, SWT.LEFT); ssidListTableSsidColumn.setText("SSID"); TableColumn ssidListTableRssiColumn = new TableColumn(ssidListTable, SWT.RIGHT); ssidListTableRssiColumn.setText("強度"); roomPlayerListTable = new TableViewer(rightSashForm, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); roomPlayerListTable.getTable().setHeaderVisible(true); application.initControl(roomPlayerListTable.getTable()); TableColumn roomPlayerSsidChaseColumn = new TableColumn(roomPlayerListTable.getTable(), SWT.CENTER); SwtUtils.installSorter(roomPlayerListTable, roomPlayerSsidChaseColumn, Player.SSID_CHASE_SORTER); TableColumn roomPlayerNameColumn = new TableColumn(roomPlayerListTable.getTable(), SWT.LEFT); roomPlayerNameColumn.setText("名前"); SwtUtils.installSorter(roomPlayerListTable, roomPlayerNameColumn, Player.NANE_SORTER); TableColumn roomPlayerSsidColumn = new TableColumn(roomPlayerListTable.getTable(), SWT.LEFT); roomPlayerSsidColumn.setText("SSID"); SwtUtils.installSorter(roomPlayerListTable, roomPlayerSsidColumn, Player.SSID_SORTER); TableColumn roomPlayerPingColumn = new TableColumn(roomPlayerListTable.getTable(), SWT.RIGHT); roomPlayerPingColumn.setText("PING"); SwtUtils.installSorter(roomPlayerListTable, roomPlayerPingColumn, Player.PING_SORTER); roomPlayerListTable.setContentProvider(new Player.PlayerListContentProvider()); roomPlayerListTable.setLabelProvider(new Player.RoomPlayerLabelProvider()); SwtUtils.enableColumnDrag(roomPlayerListTable.getTable()); roomPlayerListTable.setInput(roomPlayerMap); Composite macFilteringContainer = new Composite(rightSashForm, SWT.NONE); gridLayout = new GridLayout(1, false); gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 2; gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; macFilteringContainer.setLayout(gridLayout); Label macFilteringLabel = new Label(macFilteringContainer, SWT.NONE); macFilteringLabel.setText("MACアドレス フィルタリング"); macFilteringLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); application.initControl(macFilteringLabel); SashForm macFilteringSashForm = new SashForm(macFilteringContainer, SWT.HORIZONTAL); macFilteringSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Composite macFilteringWhiteListContainer = new Composite(macFilteringSashForm, SWT.NONE); macFilteringWhiteListContainer.setLayout(gridLayout); macFilteringWhiteListCheck = new Button(macFilteringWhiteListContainer, SWT.CHECK | SWT.FLAT); macFilteringWhiteListCheck.setText("ホワイトリストを有効化"); application.initControl(macFilteringWhiteListCheck); macFilteringWhiteList = new List(macFilteringWhiteListContainer, SWT.BORDER | SWT.SINGLE); macFilteringWhiteList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); application.initControl(macFilteringWhiteList); Composite macFilteringBlackListContainer = new Composite(macFilteringSashForm, SWT.NONE); macFilteringBlackListContainer.setLayout(gridLayout); macFilteringBlackListCheck = new Button(macFilteringBlackListContainer, SWT.CHECK | SWT.FLAT); macFilteringBlackListCheck.setText("ブラックリストを有効化"); application.initControl(macFilteringBlackListCheck); macFilteringBlackList = new List(macFilteringBlackListContainer, SWT.BORDER | SWT.SINGLE); macFilteringBlackList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); application.initControl(macFilteringBlackList); gridData = new GridData(SWT.CENTER, SWT.CENTER, false, false); gridData.heightHint = 15; statusBarContainer = new Composite(shell, SWT.NONE); gridData = new GridData(SWT.FILL, SWT.CENTER, false, false); gridData.verticalIndent = 3; statusBarContainer.setLayoutData(gridData); gridLayout = new GridLayout(8, false); gridLayout.marginHeight = 2; gridLayout.marginWidth = 3; statusBarContainer.setLayout(gridLayout); gridData = new GridData(SWT.CENTER, SWT.CENTER, false, false); gridData.heightHint = 15; statusUserNameLabel = new Label(statusBarContainer, SWT.NONE); application.initControl(statusUserNameLabel); new Label(statusBarContainer, SWT.SEPARATOR | SWT.VERTICAL).setLayoutData(gridData); statusServerAddressLabel = new Label(statusBarContainer, SWT.NONE); application.initControl(statusServerAddressLabel); new Label(statusBarContainer, SWT.SEPARATOR | SWT.VERTICAL).setLayoutData(gridData); statusTunnelConnectionLabel = new Label(statusBarContainer, SWT.NONE); statusTunnelConnectionLabel.setForeground(colorRegistry.get(PlayClient.COLOR_NG)); statusTunnelConnectionLabel.setText("トンネル未接続"); application.initControl(statusTunnelConnectionLabel); new Label(statusBarContainer, SWT.SEPARATOR | SWT.VERTICAL).setLayoutData(gridData); statusTraficStatusLabel = new Label(statusBarContainer, SWT.NONE); statusTraficStatusLabel.setText("トラフィックはありません"); application.initControl(statusTraficStatusLabel); new Label(statusBarContainer, SWT.SEPARATOR | SWT.VERTICAL).setLayoutData(gridData); try { mainSashForm.setWeights(iniAppData.getRoomSashWeights()); } catch (SWTException e) { } try { centerSashForm.setWeights(iniAppData.getRoomCenterSashWeights()); } catch (SWTException e) { } try { rightSashForm.setWeights(iniAppData.getRoomRightSashWeights()); } catch (SWTException e) { } iniAppData.restorePacketMonitorTable(packetMonitorTable.getTable()); iniAppData.restoreSsidScanTable(ssidListTableViewer.getTable()); iniAppData.restoreRoomPlayerTable(roomPlayerListTable.getTable()); } private void initWidgetListeners() { shell.addShellListener(new ShellListener() { @Override public void shellActivated(ShellEvent e) { isActiveWindow = true; switch (sessionState) { case MY_ROOM_MASTER: case ROOM_MASTER: case ROOM_PARTICIPANT: changeLobbyStateTo(LobbyUserState.PLAYING); } } @Override public void shellIconified(ShellEvent e) { isActiveWindow = false; } @Override public void shellDeiconified(ShellEvent e) { isActiveWindow = true; } @Override public void shellDeactivated(ShellEvent e) { isActiveWindow = false; } @Override public void shellClosed(ShellEvent e) { } }); shell.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { myRoomEngine.closeRoom(); isPacketCapturing = false; IniAppData iniAppData = application.getAppData(); iniAppData.storeMainWindow(shell.getBounds()); iniAppData.setRoomSashWeights(mainSashForm.getWeights()); iniAppData.setRoomCenterSashWeights(centerSashForm.getWeights()); iniAppData.setRoomRightSashWeights(rightSashForm.getWeights()); iniAppData.storePacketMonitorTable(packetMonitorTable.getTable()); iniAppData.storeSsidScanTable(ssidListTableViewer.getTable()); iniAppData.storeRoomPlayerTable(roomPlayerListTable.getTable()); iniAppData.setRoomServerHistory(roomServerHistoryManager.makeCSV()); iniAppData.setRoomAddressHistory(roomAddressHistoryManager.makeCSV()); int index = wlanAdapterListCombo.getSelectionIndex() - 1; if (wlanAdapterListCombo.getItemCount() < 2 || index == -1) { iniAppData.setLastLanAdapter(""); } else { WlanDevice device = wlanAdapterList.get(index); iniAppData.setLastLanAdapter(wlanAdapterMacAddressMap.get(device)); } } }); SwtUtils.DISPLAY.addFilter(SWT.KeyUp, new Listener() { private int lastKeyCode = 0; @Override public void handleEvent(Event event) { if (!application.getSettings().isChatPresetEnableKeyInput()) return; if (!isActiveWindow) return; String msg = null; switch (event.keyCode) { case SWT.F1: msg = chatTextPresets.getPresetF1(); break; case SWT.F2: msg = chatTextPresets.getPresetF2(); break; case SWT.F3: msg = chatTextPresets.getPresetF3(); break; case SWT.F4: msg = chatTextPresets.getPresetF4(); break; case SWT.F5: msg = chatTextPresets.getPresetF5(); break; case SWT.F6: msg = chatTextPresets.getPresetF6(); break; case SWT.F7: msg = chatTextPresets.getPresetF7(); break; case SWT.F8: msg = chatTextPresets.getPresetF8(); break; case SWT.F9: msg = chatTextPresets.getPresetF9(); break; case SWT.F10: msg = chatTextPresets.getPresetF10(); break; case SWT.F11: msg = chatTextPresets.getPresetF11(); break; case SWT.F12: msg = chatTextPresets.getPresetF12(); break; case SWT.ESC: widgets.chatText.setText(""); widgets.chatText.setFocus(); lastKeyCode = event.keyCode; return; default: lastKeyCode = 0; return; } if ("".equals(msg)) return; if (lastKeyCode == event.keyCode && msg.equals(widgets.chatText.getText())) { if (sendChat(msg)) { chatText.setText(""); lastKeyCode = 0; } } else { widgets.chatText.setText(msg); widgets.chatText.setSelection(msg.length()); widgets.chatText.setFocus(); lastKeyCode = event.keyCode; } } }); formModeSelectionCombo.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { updateRoomModeSelection(); } }); formAutoModeRoomButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { switch (sessionState) { case OFFLINE: autoConnectAsMaster(); break; case ROOM_MASTER: confirmRoomDelete(false); break; case ROOM_PARTICIPANT: roomConnection.disconnect(); break; } } }); formAutoModeRoomButton.addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent e) { if (sessionState != SessionState.OFFLINE) return; if (e.button != 3) return; if (e.x < 0 || e.y < 0) return; Point size = formAutoModeRoomButton.getSize(); if (e.x > size.x || e.y > size.y) return; if (!checkConfigUserName() || !checkRoomFormTitle()) return; formAutoModeRoomButton.setEnabled(false); selectRoomServer(new ServerSelectAction() { @Override public String getOkLabel() { return "部屋を作成する"; } @Override public void select(String address) { autoConnectAsMaster(address); } @Override public void cancel() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { public void run() { cancel(); } }); return; } formAutoModeRoomButton.setEnabled(true); } catch (SWTException e) { } } }); } @Override public void mouseDown(MouseEvent e) { } @Override public void mouseDoubleClick(MouseEvent e) { } }); formManualModeRoomServerCombo.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { switch (e.character) { case SWT.CR: case SWT.LF: e.doit = false; manualConnectAsMaster(); break; } } }); formManualModeRoomServerButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (sessionState == SessionState.OFFLINE) { manualConnectAsMaster(); } else { confirmRoomDelete(false); } } }); formManualModeRoomAddressCombo.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { switch (e.character) { case SWT.CR: case SWT.LF: e.doit = false; manualConnectAsParticipant(); break; } } }); formManualModeRoomAddressButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (sessionState == SessionState.OFFLINE) { manualConnectAsParticipant(); } else { roomConnection.disconnect(); } } }); formMyRoomModeStartButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { try { if (myRoomEngine.isStarted()) { formMyRoomModeStartButton.setEnabled(false); myRoomEngine.closeRoom(); } else { startMyRoomServer(); } } catch (IOException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } }); formMyRoomModeHostText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { String host = formMyRoomModeHostText.getText(); application.getSettings().setMyRoomHostName(host); switch (sessionState) { case MY_ROOM_MASTER: roomServerAddressPort = host + ":" + formMyRoomModePortSpinner.getSelection(); updateLoginStatus(); } } }); formMyRoomModePortSpinner.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { application.getSettings().setMyRoomPort(formMyRoomModePortSpinner.getSelection()); } }); formMyRoomModeEntryButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (myRoomEntryConnection.isConnected()) { myRoomEntryConnection.disconnect(); } else { autoConnectAsMyRoom(); } } }); formMyRoomModeEntryButton.addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent e) { if (myRoomEntryConnection.isConnected()) return; if (e.button != 3) return; if (e.x < 0 || e.y < 0) return; Point size = formMyRoomModeEntryButton.getSize(); if (e.x > size.x || e.y > size.y) return; if (!checkConfigUserName() || !checkRoomFormTitle()) return; formMyRoomModeEntryButton.setEnabled(false); selectRoomServer(new ServerSelectAction() { @Override public String getOkLabel() { return "検索に登録する"; } @Override public void select(String address) { autoConnectAsMyRoom(address); } @Override public void cancel() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { public void run() { cancel(); } }); return; } formMyRoomModeEntryButton.setEnabled(true); } catch (SWTException e) { } } }); } @Override public void mouseDown(MouseEvent e) { } @Override public void mouseDoubleClick(MouseEvent e) { } }); chatText.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { switch (e.character) { case SWT.CR: case SWT.LF: e.doit = false; if (sendChat(chatText.getText())) { chatText.setText(""); } } } }); multilineChatButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { switch (sessionState) { case MY_ROOM_MASTER: case ROOM_MASTER: case ROOM_PARTICIPANT: MultiLineChatDialog dialog = new MultiLineChatDialog(shell, application); switch (dialog.open()) { case IDialogConstants.OK_ID: String message = dialog.getMessage(); sendChat(message); } } } }); chatTextPresetF1.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF1()); widgets.chatText.setFocus(); } }); chatTextPresetF2.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF2()); widgets.chatText.setFocus(); } }); chatTextPresetF3.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF3()); widgets.chatText.setFocus(); } }); chatTextPresetF4.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF4()); widgets.chatText.setFocus(); } }); chatTextPresetF5.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF5()); widgets.chatText.setFocus(); } }); chatTextPresetF6.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF6()); widgets.chatText.setFocus(); } }); chatTextPresetF7.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF7()); widgets.chatText.setFocus(); } }); chatTextPresetF8.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF8()); widgets.chatText.setFocus(); } }); chatTextPresetF9.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF9()); widgets.chatText.setFocus(); } }); chatTextPresetF10.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF10()); widgets.chatText.setFocus(); } }); chatTextPresetF11.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF11()); widgets.chatText.setFocus(); } }); chatTextPresetF12.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { sendChat(chatTextPresets.getPresetF12()); widgets.chatText.setFocus(); } }); wlanAdapterListCombo.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { int index = widgets.wlanAdapterListCombo.getSelectionIndex(); int separatorIndex = wlanAdapterList.size() + 1; int refreshIndex = separatorIndex + 1; if (index == 0) { wlanPspCommunicationButton.setEnabled(false); } else if (index < separatorIndex) { wlanPspCommunicationButton.setEnabled(true); } else if (index == separatorIndex) { wlanAdapterListCombo.select(0); wlanPspCommunicationButton.setEnabled(false); } else if (index == refreshIndex) { refreshLanAdapterList(); } } }); wlanPspCommunicationButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (wlanPspCommunicationButton.getSelection()) { if (startPacketCapturing()) { wlanPspCommunicationButton.setText("PSPと通信中"); wlanAdapterListCombo.setEnabled(false); if (currentWlanLibrary.isSSIDEnabled()) { ssidStartScan.setEnabled(true); } } else { wlanPspCommunicationButton.setSelection(false); } } else { wlanPspCommunicationButton.setEnabled(false); isPacketCapturing = false; if (currentWlanLibrary.isSSIDEnabled()) { updateSsidStartScan(false); widgets.ssidStartScan.setEnabled(false); setAndSendInformNewSSID(""); nextSsidCheckTime = 0L; } } } }); ssidScanIntervalSpinner.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { scanIntervalMillis = ssidScanIntervalSpinner.getSelection(); } }); ssidStartScan.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (!currentWlanLibrary.isSSIDEnabled() || currentWlanDevice == null) { updateSsidStartScan(false); } else { updateSsidStartScan(ssidStartScan.getSelection()); } } }); ssidListTableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent e) { if (!currentWlanLibrary.isSSIDEnabled() || currentWlanDevice == null) { return; } IStructuredSelection sel = (IStructuredSelection) e.getSelection(); WlanNetwork network = (WlanNetwork) sel.getFirstElement(); if (network == null) return; String selectedSSID = network.getSsid(); String currentSSID = ssidCurrentSsidText.getText(); if (currentSSID.equals(selectedSSID)) return; changeSSID(selectedSSID); } }); macFilteringWhiteListCheck.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.enableMacAddressWhiteList(macFilteringWhiteListCheck.getSelection()); break; case ROOM_MASTER: StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_WHITELIST_ENABLE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macFilteringWhiteListCheck.getSelection() ? "Y" : "N"); roomConnection.send(Utility.encode(sb)); break; } } }); macFilteringBlackListCheck.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.enableMacAddressBlackList(macFilteringBlackListCheck.getSelection()); break; case ROOM_MASTER: StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_BLACKLIST_ENABLE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macFilteringBlackListCheck.getSelection() ? "Y" : "N"); roomConnection.send(Utility.encode(sb)); break; } } }); formEditSaveButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { FileDialog dialog = new FileDialog(shell, SWT.SAVE); dialog.setOverwrite(true); dialog.setFilterExtensions(new String[] { "*.txt" }); String filename = dialog.open(); if (Utility.isEmpty(filename)) return; try { new File(filename).delete(); IniFile file = new IniFile(filename); IniSection section = file.getSection(null); section.set(INI_ROOM_TITLE, formTitleText.getText()); section.set(INI_ROOM_PASSWORD, formPasswordText.getText()); section.set(INI_ROOM_CAPACITY, formMaxPlayersSpiner.getSelection()); String desc = widgets.formDescriptionText.getText(); desc = desc.replace(widgets.formDescriptionText.getLineDelimiter(), "\\n"); section.set(INI_ROOM_DESCRIPTION, desc); String remarks = widgets.formRemarksText.getText(); remarks = remarks.replace(widgets.formRemarksText.getLineDelimiter(), "\\n"); section.set(INI_ROOM_REMARKS, remarks); file.saveToIni(); } catch (IOException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } }); formEditLoadButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { FileDialog dialog = new FileDialog(shell, SWT.OPEN); dialog.setFilterExtensions(new String[] { "*.txt" }); String filename = dialog.open(); if (Utility.isEmpty(filename)) return; try { IniFile file = new IniFile(filename); IniSection section = file.getSection(null); formTitleText.setText(section.get(INI_ROOM_TITLE, "")); formPasswordText.setText(section.get(INI_ROOM_PASSWORD, "")); formMaxPlayersSpiner.setSelection(section.get(INI_ROOM_CAPACITY, 4)); String desc = section.get(INI_ROOM_DESCRIPTION, ""); desc = desc.replace("\\n", formDescriptionText.getLineDelimiter()); formDescriptionText.setText(desc); String remarks = section.get(INI_ROOM_REMARKS, ""); remarks = remarks.replace("\\n", formRemarksText.getLineDelimiter()); formRemarksText.setText(remarks); } catch (IOException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } }); formEditSubmitButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { commitRoomEditForm(); } }); formTitleText.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); formPasswordText.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); formDescriptionText.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); formRemarksText.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); formManualModeRoomAddressCombo.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); formMyRoomModeHostText.addVerifyListener(SwtUtils.NOT_ACCEPT_CONTROL_CHAR_LISTENER); ModifyListener roomEditFormModifyDetectListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (isRoomInfoUpdating) return; switch (sessionState) { case MY_ROOM_MASTER: case ROOM_MASTER: formEditSubmitButton.setEnabled(true); break; } } }; widgets.formTitleText.addModifyListener(roomEditFormModifyDetectListener); widgets.formPasswordText.addModifyListener(roomEditFormModifyDetectListener); widgets.formMaxPlayersSpiner.addModifyListener(roomEditFormModifyDetectListener); widgets.formDescriptionText.addModifyListener(roomEditFormModifyDetectListener); widgets.formRemarksText.addModifyListener(roomEditFormModifyDetectListener); } private void initMenus() { Menu playerMenu = new Menu(shell, SWT.POP_UP); playerMenuChaseSsid = new MenuItem(playerMenu, SWT.CHECK); playerMenuChaseSsid.setText("このプレイヤーのSSIDを追尾"); playerMenuChaseSsid.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null) return; player.setSSIDChased(playerMenuChaseSsid.getSelection()); roomPlayerListTable.refresh(player); } }); playerMenuSetSsid = new MenuItem(playerMenu, SWT.PUSH); playerMenuSetSsid.setText("このSSIDに設定"); playerMenuSetSsid.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null) return; changeSSID(player.getSsid()); } }); playerMenuCopySsid = new MenuItem(playerMenu, SWT.PUSH); playerMenuCopySsid.setText("このSSIDをコピー"); playerMenuCopySsid.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null) return; application.putClipboard(player.getSsid()); } }); new MenuItem(playerMenu, SWT.SEPARATOR); playerMenuKick = new MenuItem(playerMenu, SWT.PUSH); playerMenuKick.setText("キック"); playerMenuKick.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null || roomLoginName.equals(player.getName())) return; String kickedName = player.getName(); switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.kickPlayer(kickedName); removeKickedRoomPlayer(kickedName); break; case ROOM_MASTER: ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_ROOM_KICK_PLAYER + TextProtocolDriver.ARGUMENT_SEPARATOR + kickedName); roomConnection.send(buf); break; } } }); new MenuItem(playerMenu, SWT.SEPARATOR); playerMenuMasterTransfer = new MenuItem(playerMenu, SWT.PUSH); playerMenuMasterTransfer.setText("部屋主を委譲"); playerMenuMasterTransfer.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null) return; String newMasterName = player.getName(); switch (sessionState) { case ROOM_MASTER: ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_ROOM_MASTER_TRANSFER + TextProtocolDriver.ARGUMENT_SEPARATOR + newMasterName); roomConnection.send(buf); if (myRoomEntryConnection.isConnected()) { myRoomEntryConnection.disconnect(); } break; } } }); roomPlayerListTable.getTable().setMenu(playerMenu); roomPlayerListTable.getTable().addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { IStructuredSelection selection = (IStructuredSelection) roomPlayerListTable.getSelection(); Player player = (Player) selection.getFirstElement(); if (player == null) { playerMenuKick.setEnabled(false); playerMenuMasterTransfer.setEnabled(false); playerMenuChaseSsid.setSelection(false); playerMenuChaseSsid.setEnabled(false); playerMenuSetSsid.setEnabled(false); playerMenuCopySsid.setEnabled(false); return; } boolean isMasterAndOtherSelected = false; switch (sessionState) { case MY_ROOM_MASTER: case ROOM_MASTER: if (!roomMasterName.equals(player.getName())) { isMasterAndOtherSelected = true; } break; } playerMenuKick.setEnabled(isMasterAndOtherSelected); if (sessionState == SessionState.ROOM_MASTER) { playerMenuMasterTransfer.setEnabled(isMasterAndOtherSelected); } else { playerMenuMasterTransfer.setEnabled(false); } boolean isSelfSelected = Utility.equals(roomLoginName, player.getName()); if (isSelfSelected || !isPacketCapturing) { playerMenuChaseSsid.setEnabled(false); playerMenuChaseSsid.setSelection(false); } else { playerMenuChaseSsid.setEnabled(currentWlanLibrary.isSSIDEnabled()); playerMenuChaseSsid.setSelection(player.isSSIDChased()); } if (Utility.isEmpty(player.getSsid())) { playerMenuSetSsid.setEnabled(false); playerMenuCopySsid.setEnabled(false); } else { playerMenuSetSsid.setEnabled(currentWlanLibrary.isSSIDEnabled() && !isSelfSelected && isPacketCapturing); playerMenuCopySsid.setEnabled(true); } } }); Menu statusServerAddressMenu = new Menu(shell, SWT.POP_UP); statusServerAddressMenuCopy = new MenuItem(statusServerAddressMenu, SWT.PUSH); statusServerAddressMenuCopy.setText("アドレスをコピー"); statusServerAddressMenuCopy.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { String roomAddress = roomServerAddressPort + ":" + roomMasterName; application.putClipboard(roomAddress); } }); statusServerAddressLabel.setMenu(statusServerAddressMenu); statusServerAddressLabel.addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { switch (sessionState) { case MY_ROOM_MASTER: case ROOM_PARTICIPANT: case ROOM_MASTER: statusServerAddressMenuCopy.setEnabled(true); break; default: statusServerAddressMenuCopy.setEnabled(false); } } }); statusTunnelConnectionMenu = new Menu(shell, SWT.POP_UP); statusTunnelConnectionMenuChangeTransport = new MenuItem(statusTunnelConnectionMenu, SWT.PUSH); statusTunnelConnectionMenuChangeTransport.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { switch (application.getSettings().getTunnelTransportLayer()) { case TCP: application.getSettings().setTunnelTransportLayer(TransportLayer.UDP); break; case UDP: application.getSettings().setTunnelTransportLayer(TransportLayer.TCP); break; } tunnelConnection.disconnect(); } }); statusTunnelConnectionLabel.addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { switch (sessionState) { case ROOM_MASTER: case ROOM_PARTICIPANT: statusTunnelConnectionLabel.setMenu(statusTunnelConnectionMenu); switch (application.getSettings().getTunnelTransportLayer()) { case TCP: statusTunnelConnectionMenuChangeTransport.setText("UDPで接続し直す"); break; case UDP: statusTunnelConnectionMenuChangeTransport.setText("TCPで接続し直す"); break; } break; default: statusTunnelConnectionLabel.setMenu(null); } } }); Menu packetMonitorMenu = new Menu(shell, SWT.POP_UP); packetMonitorMenuCopy = new MenuItem(packetMonitorMenu, SWT.PUSH); packetMonitorMenuCopy.setText("MACアドレスとユーザー名をコピー"); packetMonitorMenuCopy.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) packetMonitorTable.getSelection(); TraficStatistics stats = (TraficStatistics) selection.getFirstElement(); if (stats == null) return; application.putClipboard(stats.macAddress + "\t" + stats.playerName); } }); packetMonitorMenuWhiteList = new MenuItem(packetMonitorMenu, SWT.CHECK); packetMonitorMenuWhiteList.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) packetMonitorTable.getSelection(); TraficStatistics stats = (TraficStatistics) selection.getFirstElement(); if (stats == null || stats.isMine) return; if (macFilteringWhiteList.indexOf(stats.macAddress) == -1) { addMacAddressToWhiteList(stats.macAddress); } else { removeMacAddressFromWhiteList(stats.macAddress); } } }); packetMonitorMenuBlackList = new MenuItem(packetMonitorMenu, SWT.CHECK); packetMonitorMenuBlackList.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { IStructuredSelection selection = (IStructuredSelection) packetMonitorTable.getSelection(); TraficStatistics stats = (TraficStatistics) selection.getFirstElement(); if (stats == null || stats.isMine) return; if (macFilteringBlackList.indexOf(stats.macAddress) == -1) { addMacAddressToBlackList(stats.macAddress); } else { removeMacAddressFromBlackList(stats.macAddress); } } }); new MenuItem(packetMonitorMenu, SWT.SEPARATOR); packetMonitorMenuClear = new MenuItem(packetMonitorMenu, SWT.PUSH); packetMonitorMenuClear.setText("累積バイトをクリア"); packetMonitorMenuClear.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { synchronized (traficStatsMap) { Iterator<Entry<String, TraficStatistics>> iter = traficStatsMap.entrySet().iterator(); while (iter.hasNext()) { Entry<String, TraficStatistics> entry = iter.next(); TraficStatistics stats = entry.getValue(); stats.totalInBytes = 0; stats.totalOutBytes = 0; } } packetMonitorTable.refresh(); } }); packetMonitorTable.getTable().setMenu(packetMonitorMenu); packetMonitorTable.getTable().addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { packetMonitorMenuClear.setEnabled(traficStatsMap.size() > 0); IStructuredSelection selection = (IStructuredSelection) packetMonitorTable.getSelection(); TraficStatistics stats = (TraficStatistics) selection.getFirstElement(); boolean validStats = stats != null && !stats.isMine && !Utility.isMacBroadCastAddress(stats.macAddress); packetMonitorMenuCopy.setEnabled(validStats); packetMonitorMenuWhiteList.setEnabled(validStats); packetMonitorMenuBlackList.setEnabled(validStats); if (validStats) { boolean onWhiteList = macFilteringWhiteList.indexOf(stats.macAddress) != -1; packetMonitorMenuWhiteList.setSelection(onWhiteList); packetMonitorMenuWhiteList.setText(onWhiteList ? "ホワイトリストから削除" : "ホワイトリストに追加"); boolean onBlackList = macFilteringBlackList.indexOf(stats.macAddress) != -1; packetMonitorMenuBlackList.setSelection(onBlackList); packetMonitorMenuBlackList.setText(onBlackList ? "ブラックリストから削除" : "ブラックリストに追加"); } else { packetMonitorMenuWhiteList.setText("ホワイトリストに追加"); packetMonitorMenuBlackList.setText("ブラックリストに追加"); } } }); Menu macFilteringWhiteListMenu = new Menu(shell, SWT.POP_UP); macFilteringWhiteListMenuRemove = new MenuItem(macFilteringWhiteListMenu, SWT.PUSH); macFilteringWhiteListMenuRemove.setText("削除する"); macFilteringWhiteListMenuRemove.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { int index = macFilteringWhiteList.getSelectionIndex(); if (index == -1) return; String address = macFilteringWhiteList.getItem(index); removeMacAddressFromWhiteList(address); } }); macFilteringWhiteList.setMenu(macFilteringWhiteListMenu); macFilteringWhiteList.addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { macFilteringWhiteListMenuRemove.setEnabled(macFilteringWhiteList.getSelectionIndex() != -1); } }); Menu macFilteringBlackListMenu = new Menu(shell, SWT.POP_UP); macFilteringBlackListMenuRemove = new MenuItem(macFilteringBlackListMenu, SWT.PUSH); macFilteringBlackListMenuRemove.setText("削除する"); macFilteringBlackListMenuRemove.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { int index = macFilteringBlackList.getSelectionIndex(); if (index == -1) return; String address = macFilteringBlackList.getItem(index); removeMacAddressFromBlackList(address); } }); macFilteringBlackList.setMenu(macFilteringBlackListMenu); macFilteringBlackList.addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { macFilteringBlackListMenuRemove.setEnabled(macFilteringBlackList.getSelectionIndex() != -1); } }); } private void updateChatPresetButtons() { IniSettings settings = application.getSettings(); String msg; int maxLength = settings.getChatPresetButtonMaxLength(); if (maxLength < 1) { maxLength = 1; settings.setChatPresetButtonMaxLength(maxLength); } msg = chatTextPresets.getPresetF1(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF1.setText("1:" + msg); chatTextPresetF1.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF2(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF2.setText("2:" + msg); chatTextPresetF2.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF3(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF3.setText("3:" + msg); chatTextPresetF3.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF4(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF4.setText("4:" + msg); chatTextPresetF4.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF5(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF5.setText("5:" + msg); chatTextPresetF5.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF6(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF6.setText("6:" + msg); chatTextPresetF6.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF7(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF7.setText("7:" + msg); chatTextPresetF7.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF8(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF8.setText("8:" + msg); chatTextPresetF8.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF9(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF9.setText("9:" + msg); chatTextPresetF9.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF10(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF10.setText("10:" + msg); chatTextPresetF10.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF11(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF11.setText("11:" + msg); chatTextPresetF11.setEnabled(msg.length() > 0); msg = chatTextPresets.getPresetF12(); msg = msg.length() > maxLength ? msg.substring(0, maxLength) : msg; chatTextPresetF12.setText("12:" + msg); chatTextPresetF12.setEnabled(msg.length() > 0); GridData data = (GridData) chatPresetContainer.getLayoutData(); data.exclude = !application.getSettings().isShowChatPresetButtons(); chatPresetContainer.getParent().layout(true, true); } } @Override public Type getType() { return Type.ROOM; } @Override public void settingChanged() { widgets.updateChatPresetButtons(); WlanLibrary library = application.getSettings().getWlanLibrary(); if (library != currentWlanLibrary && currentWlanDevice == WlanDevice.NULL) { currentWlanLibrary = library; refreshLanAdapterList(); } } private void initBackgroundThreads() { packetCaptureThread = new Thread(new Runnable() { @Override public void run() { Runnable prepareCaptureEndAction = new Runnable() { @Override public void run() { try { isPacketCapturing = false; widgets.wlanPspCommunicationButton.setEnabled(false); } catch (SWTException e) { } } }; Runnable captureEndAction = new Runnable() { @Override public void run() { try { widgets.wlanAdapterListCombo.setEnabled(true); widgets.wlanPspCommunicationButton.setText("PSPと通信開始"); widgets.wlanPspCommunicationButton.setEnabled(true); WlanLibrary library = application.getSettings().getWlanLibrary(); if (library != currentWlanLibrary) { currentWlanLibrary = library; refreshLanAdapterList(); } if (currentWlanLibrary.isSSIDEnabled()) updateSsidStartScan(false); } catch (SWTException e) { } } }; try { while (!shell.isDisposed()) { synchronized (packetCaptureThread) { if (!isPacketCapturing) packetCaptureThread.wait(); } try { while (isPacketCapturing) { bufferForCapturing.clear(); int ret = currentWlanDevice.capturePacket(bufferForCapturing); if (ret > 0) { bufferForCapturing.flip(); processCapturedPacket(); } else if (ret == 0) { } else { SwtUtils.DISPLAY.syncExec(prepareCaptureEndAction); break; } } } catch (Exception e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); isPacketCapturing = false; } currentWlanDevice.close(); currentWlanDevice = WlanDevice.NULL; SwtUtils.DISPLAY.syncExec(captureEndAction); } } catch (SWTException e) { } catch (Exception e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } }, "PacketCaptureThread"); packetCaptureThread.setDaemon(true); wlanScannerThread = new Thread(new Runnable() { @Override public void run() { final ArrayList<WlanNetwork> networkList = new ArrayList<WlanNetwork>(); Runnable refreshAction = new Runnable() { @Override public void run() { try { if (widgets.ssidAutoDetectCheck.getSelection()) { String currentSSID = widgets.ssidCurrentSsidText.getText(); String match = widgets.ssidMatchText.getText(); for (WlanNetwork bssid : networkList) { String ssid = bssid.getSsid(); if (!ssid.equals(currentSSID) && ssid.startsWith(match)) { changeSSID(ssid); break; } } } else { checkSsidChange(); } widgets.ssidListTableViewer.setInput(networkList); widgets.ssidListTableViewer.refresh(); } catch (SWTException e) { } } }; Runnable clearAction = new Runnable() { @Override public void run() { try { networkList.clear(); widgets.ssidListTableViewer.setInput(networkList); widgets.ssidListTableViewer.refresh(); } catch (SWTException e) { } } }; try { while (!shell.isDisposed()) { synchronized (wlanScannerThread) { while (!isSSIDScaning) wlanScannerThread.wait(); } while (isSSIDScaning) { long nextIteration = System.currentTimeMillis() + scanIntervalMillis; networkList.clear(); currentWlanDevice.findNetworks(networkList); SwtUtils.DISPLAY.syncExec(refreshAction); currentWlanDevice.scanNetwork(); long diff = nextIteration - System.currentTimeMillis(); if (diff > 0) Thread.sleep(diff); } SwtUtils.DISPLAY.asyncExec(clearAction); } } catch (SWTException e) { } catch (InterruptedException e) { } } }, "WlanScannerThread"); wlanScannerThread.setDaemon(true); packetMonitorThread = new Thread(new Runnable() { @Override public void run() { int intervalMillis = 1000; Runnable refreshAction = new Runnable() { @Override public void run() { try { checkSsidChange(); widgets.packetMonitorTable.setInput(traficStatsMap); widgets.packetMonitorTable.refresh(); } catch (SWTException e) { } } }; Runnable clearAction = new Runnable() { @Override public void run() { try { synchronized (traficStatsMap) { traficStatsMap.clear(); } widgets.packetMonitorTable.setInput(traficStatsMap); } catch (SWTException e) { } } }; try { while (!shell.isDisposed()) { synchronized (packetMonitorThread) { if (!isPacketCapturing && !tunnelIsLinked) packetMonitorThread.wait(); } while (isPacketCapturing || tunnelIsLinked) { long deadlineTime = System.currentTimeMillis() - 10000; synchronized (traficStatsMap) { Iterator<Entry<String, TraficStatistics>> iter = traficStatsMap.entrySet().iterator(); while (iter.hasNext()) { Entry<String, TraficStatistics> entry = iter.next(); TraficStatistics stats = entry.getValue(); if (stats.lastModified < deadlineTime) { iter.remove(); continue; } stats.currentInKbps = ((double) stats.currentInBytes) * 8 / intervalMillis; stats.currentOutKbps = ((double) stats.currentOutBytes) * 8 / intervalMillis; stats.currentInBytes = 0; stats.currentOutBytes = 0; } String text; if (actualSentBytes == 0 && actualRecievedBytes == 0) { text = " トラフィックはありません "; } else { double totalInKbps = ((double) actualRecievedBytes) * 8 / intervalMillis; double totalOutKbps = ((double) actualSentBytes) * 8 / intervalMillis; text = String.format(" In: %.1f Kbps Out: %.1f Kbps ", totalInKbps, totalOutKbps); actualSentBytes = 0; actualRecievedBytes = 0; } updateTraficStatus(text); } SwtUtils.DISPLAY.syncExec(refreshAction); Thread.sleep(intervalMillis); } SwtUtils.DISPLAY.syncExec(clearAction); } } catch (SWTException e) { } catch (InterruptedException e) { } } }, "PacketMonitorThread"); packetMonitorThread.setDaemon(true); } private void wakeupThread(Thread thread) { synchronized (thread) { if (thread.isAlive()) { thread.notify(); return; } } thread.start(); } public void show() { shell.open(); } public void hide() { shell.setVisible(false); } public void reflectAppearance() { widgets.logViewer.applyAppearance(); shell.layout(true, true); } private long nextPingTime = 0L; public void cronJob() { switch (sessionState) { case ROOM_MASTER: case ROOM_PARTICIPANT: long now = System.currentTimeMillis(); if (now < nextPingTime) return; ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_PING + TextProtocolDriver.ARGUMENT_SEPARATOR + now); roomConnection.send(buf); nextPingTime = now + 5000; break; } } private void connectToRoomServer(final InetSocketAddress socketAddress) { Runnable task = new Runnable() { @Override public void run() { try { application.connectTcp(socketAddress, roomProtocol); return; } catch (SocketTimeoutException e) { ErrorLog log = new ErrorLog("サーバーに接続できませんでした"); widgets.logViewer.appendMessage(log); } catch (IOException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); } catch (RuntimeException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); } changeStateTo(SessionState.OFFLINE); } }; application.execute(task); } private interface ServerSelectAction { public String getOkLabel(); public void select(String address); public void cancel(); } private void selectRoomServer(final ServerSelectAction action) { PortalQuery query = new PortalQuery() { @Override public String getCommand() { return ProtocolConstants.Portal.COMMAND_LIST_ROOM_SERVERS; } @Override public void failCallback(ErrorLog log) { action.cancel(); widgets.logViewer.appendMessage(log); } @Override public void successCallback(String message) { ArrayList<RoomServerInfo> list = new ArrayList<RoomServerInfo>(); for (String info : message.split("\n")) { try { String[] values = info.split("\t"); String address = values[0]; int currentRooms = Integer.parseInt(values[1]); int maxRooms = Integer.parseInt(values[2]); RoomServerInfo server = new RoomServerInfo(address, currentRooms, maxRooms); list.add(server); } catch (NumberFormatException e) { } } showRoomServerSelectDialog(list, action); } }; application.queryPortalServer(query); } private void showRoomServerSelectDialog(final java.util.List<RoomServerInfo> list, final ServerSelectAction action) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { showRoomServerSelectDialog(list, action); } }); return; } if (list.isEmpty()) { ErrorLog log = new ErrorLog("ルームサーバーが見つかりません"); widgets.logViewer.appendMessage(log); action.cancel(); } else { RoomServerSelectDialog dialog = new RoomServerSelectDialog(shell, list, action.getOkLabel()); switch (dialog.open()) { case IDialogConstants.OK_ID: RoomServerInfo selected = dialog.getSelectedServer(); action.select(selected.getAddress()); break; case IDialogConstants.CANCEL_ID: action.cancel(); break; } } } catch (SWTException e) { } } private void autoConnectAsMaster() { if (!checkConfigUserName() || !checkRoomFormTitle()) return; widgets.formAutoModeRoomButton.setEnabled(false); PortalQuery query = new PortalQuery() { @Override public String getCommand() { return ProtocolConstants.Portal.COMMAND_FIND_ROOM_SERVER; } @Override public void failCallback(ErrorLog log) { revertRoomFormAutoModeButton(); widgets.logViewer.appendMessage(log); } @Override public void successCallback(String address) { autoConnectAsMaster(address); } }; application.queryPortalServer(query); } private void autoConnectAsMaster(final String address) { try { if (SwtUtils.isNotUIThread()) { if (address == null) { revertRoomFormAutoModeButton(); ErrorLog log = new ErrorLog("アドレスを取得できませんでした"); widgets.logViewer.appendMessage(log); return; } SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { autoConnectAsMaster(address); } }); return; } InetSocketAddress socketAddress = Utility.parseSocketAddress(address); if (socketAddress == null) { revertRoomFormAutoModeButton(); ErrorLog log = new ErrorLog("サーバーアドレスが正しくありません"); widgets.logViewer.appendMessage(log); return; } changeStateTo(SessionState.CONNECTING_ROOM_MASTER); roomMasterName = roomLoginName; roomServerAddressPort = address; connectToRoomServer(socketAddress); } catch (SWTException e) { } } private void revertRoomFormAutoModeButton() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { revertRoomFormAutoModeButton(); } }); return; } widgets.formAutoModeRoomButton.setEnabled(true); } catch (SWTException e) { } } public void autoConnectAsParticipant(PlayRoom room) { if (shell.getMinimized()) shell.setMinimized(false); shell.open(); if (sessionState != SessionState.OFFLINE) { ErrorLog log = new ErrorLog("現在部屋にログイン中です"); widgets.logViewer.appendMessage(log); return; } if (!checkConfigUserName()) return; InetSocketAddress socketAddress = Utility.parseSocketAddress(room.getServerAddress()); if (socketAddress == null) { ErrorLog log = new ErrorLog("サーバーアドレスが正しくありません"); widgets.logViewer.appendMessage(log); return; } widgets.formModeSelectionCombo.select(0); updateRoomModeSelection(); changeStateTo(SessionState.CONNECTING_ROOM_PARTICIPANT); roomMasterName = room.getMasterName(); roomServerAddressPort = room.getServerAddress(); connectToRoomServer(socketAddress); } private void manualConnectAsMaster() { if (!checkConfigUserName() || !checkRoomFormTitle()) return; String address = widgets.formManualModeRoomServerCombo.getText(); if (Utility.isEmpty(address)) { ErrorLog log = new ErrorLog("サーバーアドレスを入力してください"); widgets.logViewer.appendMessage(log); return; } InetSocketAddress socketAddress = Utility.parseSocketAddress(address); if (socketAddress == null) { ErrorLog log = new ErrorLog("サーバーアドレスが正しくありません"); widgets.logViewer.appendMessage(log); return; } changeStateTo(SessionState.CONNECTING_ROOM_MASTER); if (socketAddress.getAddress().isLoopbackAddress()) { roomServerAddressPort = ":" + socketAddress.getPort(); } else { roomServerAddressPort = address; } roomMasterName = roomLoginName; connectToRoomServer(socketAddress); } private void manualConnectAsParticipant() { if (!checkConfigUserName()) return; String address = widgets.formManualModeRoomAddressCombo.getText(); if (Utility.isEmpty(address)) { ErrorLog log = new ErrorLog("サーバーアドレスを入力してください"); widgets.logViewer.appendMessage(log); return; } String[] tokens = address.split(":", 3); roomMasterName = null; switch (tokens.length) { case 2: roomMasterName = ""; break; case 3: roomMasterName = tokens[2]; break; default: ErrorLog log = new ErrorLog("サーバーアドレスが正しくありません"); widgets.logViewer.appendMessage(log); return; } InetSocketAddress socketAddress = Utility.parseSocketAddress(tokens[0], tokens[1]); if (socketAddress == null) { ErrorLog log = new ErrorLog("サーバーアドレスが正しくありません"); widgets.logViewer.appendMessage(log); return; } changeStateTo(SessionState.CONNECTING_ROOM_PARTICIPANT); if (socketAddress.getAddress().isLoopbackAddress()) { roomServerAddressPort = ":" + socketAddress.getPort(); if (roomMasterName.equals("")) { widgets.formManualModeRoomAddressCombo.setText(roomServerAddressPort); } else { widgets.formManualModeRoomAddressCombo.setText(roomServerAddressPort + ":" + roomMasterName); } } else { roomServerAddressPort = Utility.socketAddressToStringByHostName(socketAddress); } connectToRoomServer(socketAddress); } private void startMyRoomServer() throws IOException { int port = widgets.formMyRoomModePortSpinner.getSelection(); if (!checkConfigUserName()) return; String title = widgets.formTitleText.getText(); if (Utility.isEmpty(title)) { RoomLog log = new RoomLog("部屋名を入力してください"); widgets.logViewer.appendMessage(log); widgets.formTitleText.setFocus(); return; } myRoomEngine.setTitle(title); myRoomEngine.setMaxPlayers(widgets.formMaxPlayersSpiner.getSelection()); myRoomEngine.setPassword(widgets.formPasswordText.getText()); myRoomEngine.setDescription(widgets.formDescriptionText.getText()); myRoomEngine.setRemarks(widgets.formRemarksText.getText()); try { myRoomEngine.openRoom(port, roomLoginName); widgets.formMasterNameText.setText(roomLoginName); roomMasterName = roomLoginName; roomServerAddressPort = widgets.formMyRoomModeHostText.getText() + ":" + port; widgets.formModeSelectionCombo.setEnabled(false); widgets.formMyRoomModePortSpinner.setEnabled(false); widgets.formMyRoomModeStartButton.setEnabled(false); } catch (BindException e) { ErrorLog log = new ErrorLog("すでに同じポートが使用されています"); widgets.logViewer.appendMessage(log); } catch (RuntimeException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } private void autoConnectAsMyRoom() { if (sessionState != SessionState.MY_ROOM_MASTER) { return; } if (widgets.formEditSubmitButton.getEnabled()) { if (!commitRoomEditForm()) { widgets.formMyRoomModeStartButton.setSelection(false); return; } } widgets.formMyRoomModeEntryButton.setEnabled(false); widgets.formMyRoomModeEntryButton.setSelection(true); PortalQuery query = new PortalQuery() { @Override public String getCommand() { return ProtocolConstants.Portal.COMMAND_FIND_ROOM_SERVER; } @Override public void failCallback(ErrorLog log) { updateMyRoomEntryForm(true); widgets.logViewer.appendMessage(log); } @Override public void successCallback(String address) { autoConnectAsMyRoom(address); } }; application.queryPortalServer(query); } private void autoConnectAsMyRoom(final String address) { try { if (SwtUtils.isNotUIThread()) { if (address == null) { updateMyRoomEntryForm(false); ErrorLog log = new ErrorLog("アドレスを取得できませんでした"); widgets.logViewer.appendMessage(log); return; } SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { autoConnectAsMyRoom(address); } }); return; } widgets.formMyRoomModeRoomServer.setText(address); Runnable task = new Runnable() { @Override public void run() { try { InetSocketAddress socketAddress = Utility.parseSocketAddress(address); application.connectTcp(socketAddress, myRoomEntryProtocol); return; } catch (IOException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); } catch (RuntimeException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); } updateMyRoomEntryForm(false); } }; application.execute(task); } catch (SWTException e) { } } private void updateMyRoomEntryForm(final boolean entryOn) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateMyRoomEntryForm(entryOn); } }); return; } if (entryOn) { widgets.formMyRoomModeEntryButton.setText("検索解除"); widgets.formMyRoomModeEntryButton.setSelection(true); widgets.formMyRoomModeEntryButton.setEnabled(true); widgets.formMyRoomModeHostText.setEnabled(false); } else { widgets.formMyRoomModeRoomServer.setText(""); widgets.formMyRoomModeEntryButton.setText("検索登録"); widgets.formMyRoomModeEntryButton.setSelection(false); widgets.formMyRoomModeEntryButton.setEnabled(sessionState != SessionState.OFFLINE); widgets.formMyRoomModeHostText.setEnabled(true); } } catch (SWTException e) { } } private void addMacAddressToWhiteList(String macAddress) { switch (sessionState) { case MY_ROOM_MASTER: { myRoomEngine.addMacAddressToWhiteList(macAddress); break; } case ROOM_MASTER: { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_WHITELIST_ADD); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macAddress); roomConnection.send(Utility.encode(sb)); break; } } widgets.macFilteringWhiteList.add(macAddress); } private void removeMacAddressFromWhiteList(String macAddress) { switch (sessionState) { case MY_ROOM_MASTER: { myRoomEngine.removeMacAddressFromWhiteList(macAddress); break; } case ROOM_MASTER: { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_WHITELIST_REMOVE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macAddress); roomConnection.send(Utility.encode(sb)); break; } } widgets.macFilteringWhiteList.remove(macAddress); } private void addMacAddressToBlackList(String macAddress) { switch (sessionState) { case MY_ROOM_MASTER: { myRoomEngine.addMacAddressToBlackList(macAddress); break; } case ROOM_MASTER: { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_BLACKLIST_ADD); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macAddress); roomConnection.send(Utility.encode(sb)); break; } } widgets.macFilteringBlackList.add(macAddress); } private void removeMacAddressFromBlackList(String macAddress) { switch (sessionState) { case MY_ROOM_MASTER: { myRoomEngine.removeMacAddressFromBlackList(macAddress); break; } case ROOM_MASTER: { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_BLACKLIST_REMOVE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(macAddress); roomConnection.send(Utility.encode(sb)); break; } } widgets.macFilteringBlackList.remove(macAddress); } private boolean checkConfigUserName() { IniUserProfile profile = application.getUserProfile(); String name = profile.getUserName(); if (Utility.isEmpty(name)) { application.openConfigDialog(shell, MiscSettingPage.PAGE_ID); name = profile.getUserName(); if (Utility.isEmpty(name)) return false; } roomLoginName = name; return true; } private boolean checkRoomFormTitle() { String title = widgets.formTitleText.getText(); if (Utility.isEmpty(title)) { RoomLog log = new RoomLog("部屋名を入力してください"); widgets.logViewer.appendMessage(log); widgets.formTitleText.setFocus(); return false; } return true; } int confirmRoomDelete(boolean onExit) { switch (sessionState) { case ROOM_MASTER: { if (roomPlayerMap.size() < 2) { if (onExit) { return -1; } else { roomConnection.disconnect(); return 1; } } RoomDeleteDialog dialog = new RoomDeleteDialog(shell); dialog.open(); switch (dialog.getSelection()) { case LOGOUT: roomConnection.disconnect(); return 1; case DESTROY: roomConnection.send(Utility.encode(ProtocolConstants.Room.COMMAND_ROOM_DELETE)); return 1; case CANCEL: return 0; } break; } case MY_ROOM_MASTER: { ConfirmDialog dialog = new ConfirmDialog(shell, "マイルームが起動したままです", "マイルームを閉じます。よろしいですか?"); switch (dialog.open()) { case IDialogConstants.OK_ID: myRoomEngine.closeRoom(); return 1; case IDialogConstants.CANCEL_ID: return 0; } break; } } return -1; } private void appendRoomInfo(StringBuilder sb) { sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formMaxPlayersSpiner.getText()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formTitleText.getText()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formPasswordText.getText()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formDescriptionText.getText()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formRemarksText.getText()); } private boolean commitRoomEditForm() { String title = widgets.formTitleText.getText(); if (Utility.isEmpty(title)) { ErrorLog log = new ErrorLog("部屋名を入力してください"); widgets.logViewer.appendMessage(log); widgets.formTitleText.setFocus(); return false; } widgets.formEditSubmitButton.setEnabled(false); switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.setTitle(title); myRoomEngine.setMaxPlayers(widgets.formMaxPlayersSpiner.getSelection()); myRoomEngine.setPassword(widgets.formPasswordText.getText()); myRoomEngine.setDescription(widgets.formDescriptionText.getText()); myRoomEngine.setRemarks(widgets.formRemarksText.getText()); myRoomEngine.updateRoom(); RoomLog log = new RoomLog("部屋情報を更新しました"); widgets.logViewer.appendMessage(log); widgets.chatText.setFocus(); sendMyRoomUpdate(); break; case ROOM_MASTER: StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_ROOM_UPDATE); appendRoomInfo(sb); roomConnection.send(Utility.encode(sb)); break; } return true; } private boolean sendChat(String message) { if (!Utility.isEmpty(message)) { switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.sendChat(message); return true; case ROOM_MASTER: case ROOM_PARTICIPANT: ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_CHAT + TextProtocolDriver.ARGUMENT_SEPARATOR + message); roomConnection.send(buf); return true; default: InfoLog log = new InfoLog("サーバーにログインしていません"); widgets.logViewer.appendMessage(log); } } return false; } private void processChat(String player, String message) { boolean isMine = roomLoginName.equals(player); String name = player; for (String line : message.replace("\r", "").split("\n", -1)) { Chat chat = new Chat(name, line, isMine); widgets.logViewer.appendMessage(chat); name = ""; } Chat chat = new Chat(player, message, roomLoginName.equals(player)); if (!isMine && !isActiveWindow && application.getSettings().isBallonNotifyRoom()) { application.balloonNotify(shell, "<" + player + "> " + message); } application.roomMessageReceived(chat); } private void processAdminNotify(String message) { for (String line : message.replace("\r", "").split("\n", -1)) { AdminNotify log = new AdminNotify(line); widgets.logViewer.appendMessage(log); } if (!isActiveWindow) application.balloonNotify(shell, message); } private void checkSsidChange() { if (System.currentTimeMillis() < nextSsidCheckTime) return; String latestSSID = currentWlanDevice.getSSID(); if (latestSSID == null) latestSSID = ""; String currentSSID = widgets.ssidCurrentSsidText.getText(); if (!latestSSID.equals(currentSSID)) setAndSendInformNewSSID(latestSSID); if (isPacketCapturing && application.getSettings().isSsidAutoScan()) if ("".equals(latestSSID) && !widgets.ssidStartScan.getSelection()) { widgets.ssidStartScan.setSelection(true); updateSsidStartScan(true); } nextSsidCheckTime = System.currentTimeMillis() + 3000; } private void changeSSID(String newSSID) { if (!Utility.isEmpty(newSSID)) currentWlanDevice.setSSID(newSSID); setAndSendInformNewSSID(newSSID); updateSsidStartScan(false); nextSsidCheckTime = System.currentTimeMillis() + 7000; } private void setAndSendInformNewSSID(String latestSSID) { widgets.ssidCurrentSsidText.setText(latestSSID); updateRoomPlayerSSID(roomLoginName, latestSSID); switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.informSSID(latestSSID); break; case ROOM_MASTER: case ROOM_PARTICIPANT: if (roomConnection.isConnected()) { ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_INFORM_SSID + TextProtocolDriver.ARGUMENT_SEPARATOR + latestSSID); roomConnection.send(buf); } break; } } private void updateSsidStartScan(boolean startScan) { if (!currentWlanLibrary.isSSIDEnabled()) return; isSSIDScaning = startScan; widgets.ssidStartScan.setSelection(isSSIDScaning); widgets.ssidStartScan.setText(isSSIDScaning ? "スキャン中" : "スキャン開始"); if (isSSIDScaning) wakeupThread(wlanScannerThread); } private void updateLoginStatus() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateLoginStatus(); } }); return; } switch (sessionState) { case OFFLINE: widgets.statusUserNameLabel.setText("部屋にログインしていません"); widgets.statusServerAddressLabel.setText("部屋アドレス なし"); break; default: String roomAddress; if (roomMasterName.equals("")) { roomAddress = roomServerAddressPort; } else { roomAddress = roomServerAddressPort + ":" + roomMasterName; } widgets.statusUserNameLabel.setText("ユーザー名: " + roomLoginName); widgets.statusServerAddressLabel.setText("部屋アドレス " + roomAddress); } widgets.statusBarContainer.layout(); } catch (SWTException e) { } } private void updateTunnelStatus(final boolean isLinked) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateTunnelStatus(isLinked); } }); return; } tunnelIsLinked = isLinked; if (tunnelIsLinked) wakeupThread(packetMonitorThread); ColorRegistry colorRegistry = application.getColorRegistry(); if (tunnelIsLinked) { widgets.statusTunnelConnectionLabel.setForeground(colorRegistry.get(PlayClient.COLOR_OK)); StringBuilder sb = new StringBuilder(); if (sessionState != SessionState.MY_ROOM_MASTER) switch (application.getSettings().getTunnelTransportLayer()) { case TCP: sb.append("TCP"); break; case UDP: sb.append("UDP"); break; } sb.append("トンネル接続中"); widgets.statusTunnelConnectionLabel.setText(sb.toString()); } else { widgets.statusTunnelConnectionLabel.setForeground(colorRegistry.get(PlayClient.COLOR_NG)); widgets.statusTunnelConnectionLabel.setText("トンネル未接続"); } widgets.statusBarContainer.layout(); } catch (SWTException e) { } } private void updateTraficStatus(final String text) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateTraficStatus(text); } }); return; } widgets.statusTraficStatusLabel.setText(text); widgets.statusBarContainer.layout(); } catch (SWTException e) { } } private void replaceRoomPlayerList(final String[] playerInfoList) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { replaceRoomPlayerList(playerInfoList); } }); return; } TableViewer viewer = widgets.roomPlayerListTable; viewer.getTable().clearAll(); roomPlayerMap.clear(); for (int i = 0; i < playerInfoList.length - 1; i++) { String name = playerInfoList[i]; String ssid = playerInfoList[++i]; if (Utility.isEmpty(name)) continue; Player player = new Player(name); player.setSsid(name.equals(roomLoginName) ? widgets.ssidCurrentSsidText.getText() : ssid); roomPlayerMap.put(name, player); viewer.add(player); } viewer.refresh(); } catch (SWTException e) { } } private void addRoomPlayer(final String name) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { addRoomPlayer(name); } }); return; } TableViewer viewer = widgets.roomPlayerListTable; InfoLog log = new InfoLog(name + " が入室しました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); Player player = new Player(name); roomPlayerMap.put(name, player); viewer.add(player); viewer.refresh(); sendMyRoomPlayerCountChange(); } catch (SWTException e) { } } private void removeRoomPlayer(final String name) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { removeRoomPlayer(name); } }); return; } TableViewer viewer = widgets.roomPlayerListTable; Player player = roomPlayerMap.remove(name); if (player == null) return; viewer.remove(player); viewer.refresh(); sendMyRoomPlayerCountChange(); } catch (SWTException e) { } } private void removeExitingRoomPlayer(String name) { InfoLog log = new InfoLog(name + " が退室しました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); removeRoomPlayer(name); } private void removeKickedRoomPlayer(String name) { switch (sessionState) { case MY_ROOM_MASTER: case ROOM_MASTER: { RoomLog log = new RoomLog(name + " を部屋から追い出しました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); break; } case ROOM_PARTICIPANT: { RoomLog log = new RoomLog(name + " は部屋から追い出されました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); break; } } removeRoomPlayer(name); } private void updateRoomPlayerPing(final String name, final int ping) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateRoomPlayerPing(name, ping); } }); return; } HashMap<String, Player> map = roomPlayerMap; Player player = map.get(name); if (player == null) return; player.setPing(ping); widgets.roomPlayerListTable.refresh(player); } catch (SWTException e) { } } private void updateRoomPlayerSSID(final String name, final String ssid) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateRoomPlayerSSID(name, ssid); } }); return; } Player player = roomPlayerMap.get(name); if (player == null) return; player.setSsid(ssid); widgets.roomPlayerListTable.refresh(player); if (player.isSSIDChased() && isPacketCapturing) { changeSSID(ssid); } } catch (SWTException e) { } } private void updateRoom(final String[] tokens, final boolean isInitialUpdate) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { updateRoom(tokens, isInitialUpdate); } }); return; } String masterName = tokens[0]; int maxPlayers = Integer.parseInt(tokens[1]); String title = tokens[2]; String password = tokens[3]; long created = Long.parseLong(tokens[4]); String description = tokens[5]; String remarks = tokens[6]; isRoomInfoUpdating = true; widgets.formMasterNameText.setText(masterName); widgets.formMaxPlayersSpiner.setSelection(maxPlayers); widgets.formTitleText.setText(title); widgets.formPasswordText.setText(password); widgets.formTimestampText.setText(PlayRoomUtils.DATE_FORMAT.format(new Date(created))); widgets.formDescriptionText.setText(description); widgets.formRemarksText.setText(remarks); isRoomInfoUpdating = false; widgets.formEditSubmitButton.setEnabled(false); if (isInitialUpdate) return; RoomLog log; log = new RoomLog("部屋情報が更新されました"); widgets.logViewer.appendMessage(log); if (!masterName.equals(roomMasterName)) { roomMasterName = masterName; log = new RoomLog("部屋主が " + roomMasterName + " に変更されました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); updateLoginStatus(); if (masterName.equals(roomLoginName)) { changeStateTo(SessionState.ROOM_MASTER); } else if (sessionState == SessionState.ROOM_MASTER) { widgets.formManualModeRoomAddressCombo.setEnabled(false); widgets.formManualModeRoomAddressCombo.setText(roomServerAddressPort + ":" + masterName); changeStateTo(SessionState.ROOM_PARTICIPANT); } else { widgets.formManualModeRoomAddressCombo.setText(roomServerAddressPort + ":" + masterName); } } } catch (NumberFormatException e) { } catch (SWTException e) { } } private void changeLobbyStateTo(LobbyUserState userState) { ArenaWindow window = application.getArenaWindow(); if (window != null) window.changeLobbyStateTo(userState); } private void changeStateTo(final SessionState state) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { changeStateTo(state); } }); return; } sessionState = state; switch (state) { case OFFLINE: updateLoginStatus(); roomPlayerMap.clear(); widgets.roomPlayerListTable.refresh(); widgets.formEditSubmitButton.setEnabled(false); widgets.formEditLoadButton.setEnabled(true); setEnableRoomFormItems(true); setEnableMacFilteringControls(true); widgets.formMasterNameText.setText(""); widgets.formTimestampText.setText(""); widgets.formModeSelectionCombo.setEnabled(true); widgets.formAutoModeServerAddress.setText(""); widgets.formAutoModeRoomButton.setText("部屋を作成する"); widgets.formAutoModeRoomButton.setEnabled(true); widgets.formAutoModeContainer.layout(); widgets.formManualModeRoomServerCombo.setEnabled(true); widgets.formManualModeRoomServerButton.setText("部屋作成"); widgets.formManualModeRoomServerButton.setEnabled(true); widgets.formManualModeRoomAddressCombo.setEnabled(true); widgets.formManualModeRoomAddressButton.setText("入室する"); widgets.formManualModeRoomAddressButton.setEnabled(true); // window.roomFormManualModeContainer.layout(); widgets.formMyRoomModePortSpinner.setEnabled(true); widgets.formMyRoomModeStartButton.setText("起動する"); widgets.formMyRoomModeStartButton.setEnabled(true); widgets.formMyRoomModeEntryButton.setEnabled(false); switch (widgets.formModeSelectionCombo.getSelectionIndex()) { case 0: break; case 1: break; case 2: updateTunnelStatus(false); break; } changeLobbyStateTo(LobbyUserState.LOGIN); break; case MY_ROOM_MASTER: widgets.formMyRoomModeStartButton.setText("停止する"); widgets.formMyRoomModeStartButton.setEnabled(true); widgets.formMyRoomModeEntryButton.setEnabled(true); updateTunnelStatus(true); if (widgets.macFilteringWhiteList.getItemCount() > 0) { for (String mac : widgets.macFilteringWhiteList.getItems()) { myRoomEngine.addMacAddressToWhiteList(mac); } } if (widgets.macFilteringBlackList.getItemCount() > 0) { for (String mac : widgets.macFilteringBlackList.getItems()) { myRoomEngine.addMacAddressToBlackList(mac); } } widgets.chatText.setFocus(); break; case CONNECTING_ROOM_MASTER: widgets.formModeSelectionCombo.setEnabled(false); widgets.formManualModeRoomServerButton.setEnabled(false); widgets.formManualModeRoomServerCombo.setEnabled(false); widgets.formManualModeRoomAddressButton.setEnabled(false); widgets.formManualModeRoomAddressCombo.setEnabled(false); break; case ROOM_MASTER: switch (widgets.formModeSelectionCombo.getSelectionIndex()) { case 0: widgets.formAutoModeRoomButton.setText("ログアウト"); widgets.formAutoModeRoomButton.setEnabled(true); break; case 1: widgets.formManualModeRoomServerButton.setText("ログアウト"); widgets.formManualModeRoomServerButton.setEnabled(true); widgets.formManualModeRoomAddressButton.setEnabled(false); // window.roomFormManualModeContainer.layout(); break; } widgets.formEditLoadButton.setEnabled(true); setEnableRoomFormItems(true); setEnableMacFilteringControls(true); if (widgets.macFilteringWhiteList.getItemCount() > 0) { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_WHITELIST_ADD); for (String mac : widgets.macFilteringWhiteList.getItems()) { sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(mac); } roomConnection.send(Utility.encode(sb)); } if (widgets.macFilteringBlackList.getItemCount() > 0) { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_BLACKLIST_ADD); for (String mac : widgets.macFilteringBlackList.getItems()) { sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(mac); } roomConnection.send(Utility.encode(sb)); } widgets.chatText.setFocus(); break; case CONNECTING_ROOM_PARTICIPANT: widgets.formModeSelectionCombo.setEnabled(false); widgets.formManualModeRoomServerButton.setEnabled(false); widgets.formManualModeRoomServerCombo.setEnabled(false); widgets.formManualModeRoomAddressButton.setEnabled(false); widgets.formManualModeRoomAddressCombo.setEnabled(false); break; case ROOM_PARTICIPANT: switch (widgets.formModeSelectionCombo.getSelectionIndex()) { case 0: widgets.formAutoModeRoomButton.setText("退室する"); widgets.formAutoModeRoomButton.setEnabled(true); break; case 1: widgets.formManualModeRoomAddressButton.setText("退室する"); widgets.formManualModeRoomAddressButton.setEnabled(true); widgets.formManualModeRoomServerButton.setEnabled(false); // window.roomFormManualModeContainer.layout(); break; } widgets.formEditLoadButton.setEnabled(false); setEnableRoomFormItems(false); setEnableMacFilteringControls(false); widgets.chatText.setFocus(); break; } } catch (SWTException e) { } } private void updateRoomModeSelection() { switch (widgets.formModeSelectionCombo.getSelectionIndex()) { case 0: widgets.roomModeStackLayout.topControl = widgets.formAutoModeContainer; widgets.formMaxPlayersSpiner.setMaximum(ProtocolConstants.Room.MAX_ROOM_PLAYERS); break; case 1: widgets.roomModeStackLayout.topControl = widgets.formManualModeContainer; widgets.formMaxPlayersSpiner.setMaximum(ProtocolConstants.Room.MAX_ROOM_PLAYERS); break; case 2: widgets.roomModeStackLayout.topControl = widgets.formMyRoomModeContainer; widgets.formMaxPlayersSpiner.setMaximum(Integer.MAX_VALUE); break; } widgets.formModeSwitchContainer.layout(); } private void setEnableRoomFormItems(boolean enabled) { widgets.formTitleText.setEditable(enabled); widgets.formPasswordText.setEditable(enabled); widgets.formMaxPlayersSpiner.setEnabled(enabled); widgets.formDescriptionText.setEditable(enabled); widgets.formRemarksText.setEditable(enabled); } private void clearRoomForm() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { clearRoomForm(); } }); return; } widgets.formTitleText.setText(""); widgets.formPasswordText.setText(""); widgets.formMaxPlayersSpiner.setSelection(DEFAULT_MAX_PLAYERS); widgets.formDescriptionText.setText(""); widgets.formRemarksText.setText(""); } catch (SWTException e) { } } private void setEnableMacFilteringControls(boolean enabled) { widgets.macFilteringWhiteListCheck.setEnabled(enabled); widgets.macFilteringWhiteList.setEnabled(enabled); widgets.macFilteringBlackListCheck.setEnabled(enabled); widgets.macFilteringBlackList.setEnabled(enabled); if (enabled) { widgets.macFilteringWhiteListCheck.setSelection(false); widgets.macFilteringBlackListCheck.setSelection(false); } } private void sendMyRoomUpdate() { if (!myRoomEntryConnection.isConnected()) { return; } try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { sendMyRoomUpdate(); } }); return; } StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.MyRoom.COMMAND_UPDATE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formTitleText.getText()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formMaxPlayersSpiner.getSelection()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formPasswordText.getText().length() > 0 ? "Y" : "N"); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.formDescriptionText.getText()); myRoomEntryConnection.send(Utility.encode(sb)); } catch (SWTException e) { } } private void sendMyRoomPlayerCountChange() { if (myRoomEntryConnection.isConnected()) { ByteBuffer buf = Utility.encode(ProtocolConstants.MyRoom.COMMAND_UPDATE_PLAYER_COUNT + TextProtocolDriver.ARGUMENT_SEPARATOR + roomPlayerMap.size()); myRoomEntryConnection.send(buf); } } private class MyRoomEntryProtocol implements IProtocol { @Override public void log(String message) { } @Override public String getProtocol() { return ProtocolConstants.PROTOCOL_MY_ROOM_ENTRY; } @Override public IProtocolDriver createDriver(ISocketConnection connection) { myRoomEntryConnection = connection; init(connection); return new MyRoomEntryProtocolDriver(connection); } private void init(ISocketConnection connection) { StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.MyRoom.COMMAND_ENTRY); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(myRoomEngine.getAuthCode()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomServerAddressPort); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomLoginName); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(myRoomEngine.getTitle()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomPlayerMap.size()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(myRoomEngine.getMaxPlayers()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(Utility.isEmpty(myRoomEngine.getPassword()) ? "N" : "Y"); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(myRoomEngine.getCreatedTime()); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(myRoomEngine.getDescription()); connection.send(Utility.encode(sb)); } } private class MyRoomEntryProtocolDriver extends TextProtocolDriver { private boolean isEntryCompleted = false; public MyRoomEntryProtocolDriver(ISocketConnection connection) { super(connection, myRoomEntryHandlers); } @Override public void connectionDisconnected() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { connectionDisconnected(); } }); return; } updateMyRoomEntryForm(false); if (isEntryCompleted) { isEntryCompleted = false; roomServerHistoryManager.addCurrentItem(); RoomLog log = new RoomLog("マイルームの登録が解除されました"); widgets.logViewer.appendMessage(log); } else { ErrorLog log = new ErrorLog("マイルームを登録できませんでした"); widgets.logViewer.appendMessage(log); } } catch (SWTException e) { } } @Override public void log(String message) { ErrorLog log = new ErrorLog(message); widgets.logViewer.appendMessage(log); } @Override public void errorProtocolNumber(String number) { String message = String.format("サーバーとのプロトコルナンバーが一致しないので接続できません サーバー:%s クライアント:%s", number, IProtocol.NUMBER); ErrorLog log = new ErrorLog(message); widgets.logViewer.appendMessage(log); } } private HashMap<String, IProtocolMessageHandler> myRoomEntryHandlers = new HashMap<String, IProtocolMessageHandler>(); { myRoomEntryHandlers.put(ProtocolConstants.MyRoom.COMMAND_ENTRY, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { updateMyRoomEntryForm(true); MyRoomEntryProtocolDriver myroom = (MyRoomEntryProtocolDriver) driver; myroom.isEntryCompleted = true; RoomLog log = new RoomLog("マイルームを登録しました"); widgets.logViewer.appendMessage(log); return true; } }); myRoomEntryHandlers.put(ProtocolConstants.MyRoom.ERROR_TCP_PORT_NOT_OPEN, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { ErrorLog log = new ErrorLog("マイルームのTCPポートが開放されていません"); widgets.logViewer.appendMessage(log); return false; } }); myRoomEntryHandlers.put(ProtocolConstants.MyRoom.ERROR_UDP_PORT_NOT_OPEN, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { ErrorLog log = new ErrorLog("マイルームのUDPポートが開放されていません"); widgets.logViewer.appendMessage(log); return false; } }); myRoomEntryHandlers.put(ProtocolConstants.MyRoom.ERROR_INVALID_AUTH_CODE, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { ErrorLog log = new ErrorLog("マイルーム以外の登録はできません"); widgets.logViewer.appendMessage(log); return false; } }); } private class MyRoomServerHandler implements IMyRoomMasterHandler { @Override public void log(String message) { application.getArenaWindow().appendToSystemLog(message, true); } @Override public void chatReceived(String player, String message) { processChat(player, message); } @Override public void playerEntered(String player) { addRoomPlayer(player); } @Override public void playerExited(String player) { removeExitingRoomPlayer(player); } @Override public void pingInformed(String player, int ping) { updateRoomPlayerPing(player, ping); } @Override public void ssidInformed(String player, String ssid) { updateRoomPlayerSSID(player, ssid); } @Override public void tunnelPacketReceived(ByteBuffer packet, String playerName) { processRemotePspPacket(packet, playerName); } @Override public void roomOpened() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { roomOpened(); } }); return; } changeStateTo(SessionState.MY_ROOM_MASTER); updateLoginStatus(); changeLobbyStateTo(LobbyUserState.PLAYING); RoomLog log = new RoomLog("マイルームを起動しました"); widgets.logViewer.appendMessage(log); addRoomPlayer(roomLoginName); widgets.formTimestampText.setText(PlayRoomUtils.DATE_FORMAT.format(new Date(myRoomEngine.getCreatedTime()))); String ssid = widgets.ssidCurrentSsidText.getText(); updateRoomPlayerSSID(roomLoginName, ssid); myRoomEngine.informSSID(ssid); } catch (SWTException e) { } } @Override public void roomClosed() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { roomClosed(); } }); return; } if (myRoomEntryConnection.isConnected()) myRoomEntryConnection.disconnect(); changeStateTo(SessionState.OFFLINE); RoomLog log = new RoomLog("マイルームを停止しました"); widgets.logViewer.appendMessage(log); } catch (SWTException e) { } } } private class RoomProtocol implements IProtocol { @Override public void log(String message) { application.getArenaWindow().appendToSystemLog(message, true); } @Override public String getProtocol() { return ProtocolConstants.PROTOCOL_ROOM; } @Override public IProtocolDriver createDriver(ISocketConnection connection) { roomConnection = connection; init(connection); return new RoomProtocolDriver(connection); } private void init(final ISocketConnection connection) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { init(connection); } }); return; } widgets.formAutoModeServerAddress.setText(roomServerAddressPort); StringBuilder sb = new StringBuilder(); switch (sessionState) { case CONNECTING_ROOM_MASTER: { ServerLog log = new ServerLog("サーバーに接続しました"); widgets.logViewer.appendMessage(log); sb.append(ProtocolConstants.Room.COMMAND_ROOM_CREATE); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomLoginName); appendRoomInfo(sb); roomConnection.send(Utility.encode(sb)); widgets.formManualModeRoomServerCombo.setText(roomServerAddressPort); sessionState = SessionState.NEGOTIATING; break; } case CONNECTING_ROOM_PARTICIPANT: { ServerLog log = new ServerLog("サーバーに接続しました"); widgets.logViewer.appendMessage(log); sb.append(ProtocolConstants.Room.COMMAND_LOGIN); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomLoginName); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomMasterName); sb.append(TextProtocolDriver.MESSAGE_SEPARATOR); sb.append(ProtocolConstants.Room.COMMAND_INFORM_SSID); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(widgets.ssidCurrentSsidText.getText()); roomConnection.send(Utility.encode(sb)); widgets.formManualModeRoomAddressCombo.setText(roomServerAddressPort + ":" + roomMasterName); sessionState = SessionState.NEGOTIATING; break; } } } catch (SWTException e) { } } } private class RoomProtocolDriver extends TextProtocolDriver { public RoomProtocolDriver(ISocketConnection connection) { super(connection, roomHandlers); } @Override public void connectionDisconnected() { switch (sessionState) { case CONNECTING_ROOM_PARTICIPANT: case CONNECTING_ROOM_MASTER: { ErrorLog log = new ErrorLog("サーバーに接続できません"); widgets.logViewer.appendMessage(log); break; } case ROOM_PARTICIPANT: clearRoomForm(); default: ServerLog log = new ServerLog("サーバーと切断しました"); widgets.logViewer.appendMessage(log); } roomConnection = ISocketConnection.NULL; tunnelConnection.disconnect(); changeStateTo(SessionState.OFFLINE); } @Override public void log(String message) { application.getArenaWindow().appendToSystemLog(message, true); } @Override public void errorProtocolNumber(String number) { String message = String.format("サーバーとのプロトコルナンバーが一致しないので接続できません サーバー:%s クライアント:%s", number, IProtocol.NUMBER); ErrorLog log = new ErrorLog(message); widgets.logViewer.appendMessage(log); } } private void promptRoomPassword() { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { promptRoomPassword(); } }); return; } TextDialog dialog = new TextDialog(shell, "パスワードを入力してください", "部屋にパスワードが設定されています", null, 180, SWT.NONE); switch (dialog.open()) { case IDialogConstants.OK_ID: String password = dialog.getUserInput(); StringBuilder sb = new StringBuilder(); sb.append(ProtocolConstants.Room.COMMAND_LOGIN); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomLoginName); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(roomMasterName); sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR); sb.append(password); roomConnection.send(Utility.encode(sb)); break; case IDialogConstants.CANCEL_ID: RoomLog log = new RoomLog("入室をキャンセルしました"); widgets.logViewer.appendMessage(log); roomConnection.disconnect(); break; } } catch (SWTException e) { } } private HashMap<String, IProtocolMessageHandler> roomHandlers = new HashMap<String, IProtocolMessageHandler>(); { roomHandlers.put(ProtocolConstants.Room.COMMAND_ROOM_CREATE, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, final String argument) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { process(null, argument); } }); connectRoomTunnel(); return true; } long created = Long.parseLong(argument); widgets.formTimestampText.setText(PlayRoomUtils.DATE_FORMAT.format(new Date(created))); changeStateTo(SessionState.ROOM_MASTER); RoomLog log = new RoomLog("ルームサーバーで部屋を作成しました"); widgets.logViewer.appendMessage(log); widgets.formMasterNameText.setText(roomLoginName); addRoomPlayer(roomLoginName); updateLoginStatus(); changeLobbyStateTo(LobbyUserState.PLAYING); roomServerHistoryManager.addCurrentItem(); } catch (NumberFormatException e) { return false; } catch (SWTException e) { } return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_LOGIN, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, final String args) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { process(null, args); } }); connectRoomTunnel(); return true; } changeStateTo(SessionState.ROOM_PARTICIPANT); updateRoom(args.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1), true); updateLoginStatus(); changeLobbyStateTo(LobbyUserState.PLAYING); roomAddressHistoryManager.addCurrentItem(); RoomLog log = new RoomLog("部屋に入りました"); widgets.logViewer.appendMessage(log); } catch (SWTException e) { } return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_CHAT, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { String[] tokens = argument.split(TextProtocolDriver.ARGUMENT_SEPARATOR, 2); if (tokens.length != 2) return true; processChat(tokens[0], tokens[1]); return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_PINGBACK, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { try { long time = Long.parseLong(argument); int ping = (int) (System.currentTimeMillis() - time); updateRoomPlayerPing(roomLoginName, ping); ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_INFORM_PING + TextProtocolDriver.ARGUMENT_SEPARATOR + ping); roomConnection.send(buf); } catch (NumberFormatException e) { } return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_INFORM_PING, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String args) { try { switch (sessionState) { case MY_ROOM_MASTER: case ROOM_PARTICIPANT: case ROOM_MASTER: String[] values = args.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1); if (values.length == 2) { int ping = Integer.parseInt(values[1]); updateRoomPlayerPing(values[0], ping); } } } catch (NumberFormatException e) { } return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_INFORM_TUNNEL_PORT, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { updateTunnelStatus(true); application.getArenaWindow().appendToSystemLog("トンネル通信の接続が開始しました", true); return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_MAC_ADDRESS_PLAYER, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { String[] tokens = argument.split(TextProtocolDriver.ARGUMENT_SEPARATOR); if (tokens.length != 2) return true; TraficStatistics stats = traficStatsMap.get(tokens[0]); if (stats == null) return true; stats.playerName = tokens[1]; return true; } }); roomHandlers.put(ProtocolConstants.Room.COMMAND_ROOM_UPDATE, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { process(null, null); } }); return true; } RoomLog log = new RoomLog("部屋情報を修正しました"); widgets.logViewer.appendMessage(log); widgets.chatText.setFocus(); } catch (SWTException e) { } return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_USER_LIST, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String args) { // System.out.println(args); String[] playerInfoList = args.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1); replaceRoomPlayerList(playerInfoList); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_USER_ENTERED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String name) { addRoomPlayer(name); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_USER_EXITED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String name) { removeExitingRoomPlayer(name); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_ROOM_UPDATED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String args) { updateRoom(args.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1), false); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_ROOM_PLAYER_KICKED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String kickedPlayer) { if (roomLoginName.equals(kickedPlayer)) { changeStateTo(SessionState.OFFLINE); RoomLog log = new RoomLog("部屋から追い出されました"); widgets.logViewer.appendMessage(log); } else { removeKickedRoomPlayer(kickedPlayer); } return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_ROOM_PASSWORD_REQUIRED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { promptRoomPassword(); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_FROM_ADMIN, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String message) { processAdminNotify(message); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_ROOM_DELETED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { RoomLog log = new RoomLog("部屋が削除されました"); widgets.logViewer.appendMessage(log); if (!isActiveWindow && application.getSettings().isBallonNotifyRoom()) application.balloonNotify(shell, log.getMessage()); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_SSID_CHANGED, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { String[] values = argument.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1); if (values.length == 2) { updateRoomPlayerSSID(values[0], values[1]); } return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_ROOM_AGE_OLD, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { processAdminNotify("部屋作成から長時間経過しました。15分後に自動解散します。"); return true; } }); roomHandlers.put(ProtocolConstants.Room.NOTIFY_TUNNEL_COMMUNICATION_IDLE, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver driver, String argument) { processAdminNotify("無通信状態です。15分後に自動退出します。"); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_LOGIN_DUPLICATED_NAME, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("同名のユーザーが既にログインしているのでログインできません"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_LOGIN_ROOM_NOT_EXIST, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("ログインしようとしている部屋は存在しません"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_LOGIN_BEYOND_CAPACITY, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("部屋が満室なので入れません"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_ROOM_CREATE_INVALID_DATA_ENTRY, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("部屋の情報に不正な値があります"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_LOGIN_PASSWORD_FAIL, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { RoomLog log = new RoomLog("部屋パスワードが違います"); widgets.logViewer.appendMessage(log); promptRoomPassword(); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_ROOM_CREATE_DUPLICATED_NAME, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("同名のユーザーで既に部屋が作成されているので作成できません"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_ROOM_CREATE_BEYOND_LIMIT, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { RoomLog log = new RoomLog("部屋数が上限に達しましたので部屋を作成できません"); widgets.logViewer.appendMessage(log); return true; } }); roomHandlers.put(ProtocolConstants.Room.ERROR_ROOM_TRANSFER_DUPLICATED_NAME, new IProtocolMessageHandler() { @Override public boolean process(IProtocolDriver client, String argument) { ErrorLog log = new ErrorLog("同名のユーザーで既に部屋が作成されているので委譲できません"); widgets.logViewer.appendMessage(log); return true; } }); } private void connectRoomTunnel() { try { switch (application.getSettings().getTunnelTransportLayer()) { case TCP: application.connectTcp(roomConnection.getRemoteAddress(), tunnelProtocol); break; case UDP: application.connectUdp(roomConnection.getRemoteAddress(), tunnelProtocol); break; } } catch (IOException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } catch (RuntimeException e) { ErrorLog log = new ErrorLog(e); widgets.logViewer.appendMessage(log); application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); } } private class TunnelProtocol implements IProtocol { @Override public void log(String message) { application.getArenaWindow().appendToSystemLog(message, true); } @Override public String getProtocol() { return ProtocolConstants.PROTOCOL_TUNNEL; } @Override public IProtocolDriver createDriver(ISocketConnection connection) { tunnelConnection = connection; TunnelProtocolDriver driver = new TunnelProtocolDriver(connection); return driver; } } private class TunnelProtocolDriver implements IProtocolDriver { private ISocketConnection connection; private int localPort = 0; private TunnelProtocolDriver(ISocketConnection conn) { this.connection = conn; application.execute(new Runnable() { @Override public void run() { try { while (localPort == 0) { connection.send(Utility.encode(ProtocolConstants.Tunnel.DUMMY_PACKET)); Thread.sleep(10000); } } catch (InterruptedException e) { } } }); } @Override public ISocketConnection getConnection() { return connection; } @Override public boolean process(PacketData data) { ByteBuffer packet = data.getBuffer(); // System.out.println(packet.toString()); if (Utility.isPspPacket(packet)) { processRemotePspPacket(packet, null); } else { try { String port = data.getMessage(); localPort = Integer.parseInt(port); ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_INFORM_TUNNEL_PORT + TextProtocolDriver.ARGUMENT_SEPARATOR + localPort); roomConnection.send(buf); } catch (NumberFormatException e) { } } return true; } @Override public void connectionDisconnected() { updateTunnelStatus(false); tunnelConnection = ISocketConnection.NULL; application.getArenaWindow().appendToSystemLog("トンネル通信の接続が終了しました", true); if (roomConnection.isConnected()) switch (sessionState) { case ROOM_MASTER: case ROOM_PARTICIPANT: connectRoomTunnel(); } } @Override public void errorProtocolNumber(String number) { String message = String.format("サーバーとのプロトコルナンバーが一致しないので接続できません サーバー:%s クライアント:%s", number, IProtocol.NUMBER); application.getArenaWindow().appendToSystemLog(message, true); } } private void refreshLanAdapterList() { widgets.wlanAdapterListCombo.removeAll(); if (!currentWlanLibrary.isReady()) { widgets.wlanPspCommunicationButton.setEnabled(false); widgets.wlanAdapterListCombo.add("エラー: SSID機能の設定かインストールを見直してください"); widgets.wlanAdapterListCombo.select(0); widgets.wlanAdapterListCombo.setEnabled(false); return; } widgets.wlanAdapterListCombo.setEnabled(true); widgets.wlanAdapterListCombo.add("選択されていません"); try { wlanAdapterList.clear(); currentWlanLibrary.findDevices(wlanAdapterList); } catch (RuntimeException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); return; } catch (UnsatisfiedLinkError e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); return; } String lastUsedMacAddress = application.getAppData().getLastLanAdapter(); int lastUsedIndex = 0; IniSection nicSection = application.getIniSection(SECTION_LAN_ADAPTERS); int maxNameLength = 15; int i = 1; for (Iterator<WlanDevice> iter = wlanAdapterList.iterator(); iter.hasNext(); i++) { WlanDevice device = iter.next(); byte[] mac = device.getHardwareAddress(); String name; if (mac != null) { String macAddress = Utility.macAddressToString(mac, 0, true); if (lastUsedMacAddress.equals(macAddress)) { lastUsedIndex = i; } name = nicSection.get(macAddress, ""); if (Utility.isEmpty(name)) { name = device.getName(); name = name.replace("(Microsoft's Packet Scheduler)", ""); name = name.replace(" - パケット スケジューラ ミニポート", ""); name = name.replaceAll(" {2,}", " ").trim(); nicSection.set(macAddress, name); } else if (name.equals("")) { iter.remove(); continue; } name += " [" + macAddress + "]"; widgets.wlanAdapterListCombo.add(name); wlanAdapterMacAddressMap.put(device, macAddress); } else { name = device.getName(); widgets.wlanAdapterListCombo.add(name); } maxNameLength = Math.max(name.length(), maxNameLength); } StringBuilder sb = new StringBuilder(maxNameLength); for (i = 0; i < maxNameLength; i++) sb.append('-'); widgets.wlanAdapterListCombo.add(sb.toString()); widgets.wlanAdapterListCombo.add("アダプターリストを再読み込み"); widgets.wlanAdapterListCombo.select(lastUsedIndex); widgets.wlanPspCommunicationButton.setEnabled(lastUsedIndex != 0); } private void processRemotePspPacket(ByteBuffer packet, String playerName) { String destMac = Utility.macAddressToString(packet, 0, false); String srcMac = Utility.macAddressToString(packet, 6, false); // System.out.print("[" + playerName + "] "); // System.out.print("src: " + srcMac + " dest: " + destMac); // System.out.println(); TraficStatistics destStats, srcStats; synchronized (traficStatsMap) { destStats = traficStatsMap.get(destMac); srcStats = traficStatsMap.get(srcMac); if (srcStats == null) { srcStats = new TraficStatistics(srcMac, false); traficStatsMap.put(srcMac, srcStats); } if (destStats == null) { destStats = new TraficStatistics(destMac, !Utility.isMacBroadCastAddress(destMac)); traficStatsMap.put(destMac, destStats); } } int packetLength = packet.limit(); srcStats.lastModified = destStats.lastModified = System.currentTimeMillis(); if (!Utility.isEmpty(playerName)) { srcStats.playerName = playerName; } else if (Utility.isEmpty(srcStats.playerName) && !Utility.isMacBroadCastAddress(srcMac)) { ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_MAC_ADDRESS_PLAYER + TextProtocolDriver.ARGUMENT_SEPARATOR + srcMac); roomConnection.send(buf); } if (destStats.isMine) destStats.playerName = roomLoginName; actualRecievedBytes += packetLength; srcStats.currentInBytes += packetLength; srcStats.totalInBytes += packetLength; destStats.currentInBytes += packetLength; destStats.totalInBytes += packetLength; if (isPacketCapturing && currentWlanDevice != null) { currentWlanDevice.sendPacket(packet); } } private void processCapturedPacket() { // System.out.println(bufferForCapturing); if (!Utility.isPspPacket(bufferForCapturing)) return; String srcMac = Utility.macAddressToString(bufferForCapturing, 6, false); String destMac = Utility.macAddressToString(bufferForCapturing, 0, false); TraficStatistics srcStats, destStats; synchronized (traficStatsMap) { srcStats = traficStatsMap.get(srcMac); destStats = traficStatsMap.get(destMac); if (srcStats == null) { srcStats = new TraficStatistics(srcMac, true); traficStatsMap.put(srcMac, srcStats); } else if (!srcStats.isMine) { // サーバーから送られてきた他PSPからのパケットの再キャプチャなのでスルー return; } if (destStats == null) { destStats = new TraficStatistics(destMac, false); traficStatsMap.put(destMac, destStats); } else if (destStats.isMine) { // 手元のPSP同士の通信なのでスルー return; } } int packetLength = bufferForCapturing.limit(); srcStats.lastModified = destStats.lastModified = System.currentTimeMillis(); srcStats.playerName = roomLoginName; if (Utility.isEmpty(destStats.playerName) && !Utility.isMacBroadCastAddress(destMac)) { ByteBuffer buf = Utility.encode(ProtocolConstants.Room.COMMAND_MAC_ADDRESS_PLAYER + TextProtocolDriver.ARGUMENT_SEPARATOR + destMac); roomConnection.send(buf); } actualSentBytes += packetLength; srcStats.currentOutBytes += packetLength; srcStats.totalOutBytes += packetLength; destStats.currentOutBytes += packetLength; destStats.totalOutBytes += packetLength; if (!tunnelIsLinked) return; // System.out.printf("%s => %s [%d]", srcMac, destMac, // packetLength); // System.out.println(packet.toHexdump()); switch (sessionState) { case MY_ROOM_MASTER: myRoomEngine.sendTunnelPacketToParticipants(bufferForCapturing, srcMac, destMac); break; case ROOM_PARTICIPANT: case ROOM_MASTER: tunnelConnection.send(bufferForCapturing); break; } } private boolean startPacketCapturing() { try { int index = widgets.wlanAdapterListCombo.getSelectionIndex() - 1; WlanDevice device = wlanAdapterList.get(index); device.open(); currentWlanDevice = device; checkSsidChange(); isPacketCapturing = true; wakeupThread(packetCaptureThread); wakeupThread(packetMonitorThread); return true; } catch (RuntimeException e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); return false; } catch (Exception e) { application.getArenaWindow().appendToSystemLog(Utility.stackTraceToString(e), true); return false; } } }