Added all the source-files.

This commit is contained in:
Deathsbreed 2014-05-04 13:55:37 -05:00
parent 48f7f78606
commit 6417427f3d
10 changed files with 478 additions and 0 deletions

15
COPYRIGHT Normal file
View File

@ -0,0 +1,15 @@
ConsoleChat, a simple chat that can run on any machine with a Java JRE.
Copyright (C) 2014 Nicolás A. Ortega
This program 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/>.

18
WARRANTY Normal file
View File

@ -0,0 +1,18 @@
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

BIN
src-client/Client.class Normal file

Binary file not shown.

105
src-client/Client.java Normal file
View File

@ -0,0 +1,105 @@
import java.net.*;
import java.io.*;
import java.lang.*;
/**
* @author Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
* For details on the copyright, look at the COPYRIGHT file that came with
* this program.
*
*/
public class Client implements Runnable {
private String version = "v1.0";
private Socket socket = null;
private ClientThread cThread = null;
private DataOutputStream streamOut = null;
private BufferedReader console = null;
private Thread thread = null;
public static void main(String[] args) {
if(args.length != 2) {
System.out.println("Usage: java Client [server] [port]");
} else {
Client client = new Client(args[0], Integer.parseInt(args[1]));
}
}
public Client(String server, int port) {
System.out.println("ConsoleChat client " + version + " Copyright (C) 2014 Nicolás A. Ortega\n" +
"This program comes with ABSOLUTELY NO WARRANTY; details in WARRANTY file.\n" +
"This is free software, and you are welcome to redistribute it\n" +
"under certain conditions; details in LICENSE file.\n");
try {
// Create a new socket connection
System.out.println("Connecting to server...");
socket = new Socket(server, port);
System.out.println("Connected!");
start();
} catch(UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch(IOException e) {
System.out.println("Unknown exception: " + e.getMessage());
}
}
public void run() {
while(thread != null) {
try {
streamOut.writeUTF(console.readLine());
streamOut.flush();
} catch(IOException e) {
System.out.println("Sending error: " + e.getMessage());
stop();
}
}
}
public void handle(String msg) {
if(msg.equals("/quit")) {
System.out.println("Goodbye bye. Press RETURN to exit...");
stop();
} else {
System.out.println(msg);
if(msg.length() > 6 && msg.substring(0, 5).equals("Kick:")) {
stop();
}
}
}
private void start() throws IOException {
console = new BufferedReader(new InputStreamReader(System.in));
streamOut = new DataOutputStream(socket.getOutputStream());
if(thread == null) {
cThread = new ClientThread(this, socket);
thread = new Thread(this);
thread.start();
}
}
public void stop() {
if(thread != null) {
thread.interrupt();
thread = null;
}
try {
if(console != null) { console.close(); }
if(streamOut != null) { streamOut.close(); }
if(socket != null) { socket.close(); }
} catch(IOException e) {
System.out.println("Error closing...");
}
try {
cThread.close();
} catch(IOException e) {
System.out.println("Error closing the thread: " + e);
}
cThread.interrupt();
}
}

Binary file not shown.

View File

@ -0,0 +1,51 @@
import java.io.*;
import java.net.*;
/**
* @author Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
* For details on the copyright, look at the COPYRIGHT file that came with
* this program.
*
*/
public class ClientThread extends Thread {
private Socket socket = null;
private Client client = null;
private DataInputStream streamIn = null;
private boolean run = false;
public ClientThread(Client _client, Socket _socket) {
client = _client;
socket = _socket;
open();
start();
}
public void open() {
try {
streamIn = new DataInputStream(socket.getInputStream());
} catch(IOException e) {
System.out.println("Error getting input stream: " + e);
client.stop();
}
run = true;
}
public void close() throws IOException {
if(streamIn != null) { streamIn.close(); }
run = false;
}
public void run() {
while(run) {
try {
client.handle(streamIn.readUTF());
} catch(IOException e) {
System.out.println("Listening error: " + e.getMessage());
client.stop();
}
}
}
}

BIN
src-server/Server.class Normal file

Binary file not shown.

171
src-server/Server.java Normal file
View File

@ -0,0 +1,171 @@
import java.net.*;
import java.io.*;
import java.util.*;
/**
* @author Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
* For details on the copyright, look at the COPYRIGHT file that came with
* this program.
*
*/
public class Server implements Runnable {
private String version = "v1.0";
private ArrayList<ServerThread> clients = new ArrayList<ServerThread>();
private ServerSocket sSocket = null;
private Thread thread = null;
private int clientCount = 0;
private String passwd = "admin";
public static void main(String[] args) {
if(args.length != 1) {
System.out.println("You are using the program incorrectly.");
} else {
Server server = new Server(Integer.parseInt(args[0]));
}
}
public Server(int port) {
System.out.println("ConsoleChat server " + version + " Copyright (C) 2014 Nicolás A. Ortega\n" +
"This program comes with ABSOLUTELY NO WARRANTY; details in WARRANTY file.\n" +
"This is free software, and you are welcome to redistribute it\n" +
"under certain conditions; details in LICENSE file.\n");
try {
System.out.println("Binding to port " + port + "...");
// Try to open a port on the specified port number
sSocket = new ServerSocket(port);
System.out.println("Server started: " + sSocket);
start();
} catch(IOException e) {
System.out.println(e);
}
}
public void run() {
while(thread != null) {
try {
System.out.println("Waiting for clients...");
addThread(sSocket.accept());
} catch(IOException e) {
System.out.println("Acceptance error: " + e);
stop();
}
}
}
public void start() {
if(thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void stop() {
if(thread != null) {
thread.interrupt();
thread = null;
}
for(int i = 0; i < clients.size(); i++) {
try {
clients.get(i).close();
} catch(IOException e) {
System.out.println("Error closing thread: " + e);
}
}
}
public int findClient(int id) {
for(int i = 0; i < clientCount; i++) {
if(clients.get(i).getID() == id) {
return i;
}
}
return -1;
}
public synchronized void handle(int id, String username, String input) {
if(input.startsWith("/")) {
if(input.equals("/quit")) {
clients.get(findClient(id)).send("/quit");
remove(id);
} else if(input.equals("/list")) {
int pos = findClient(id);
for(int i = 0; i < clients.size(); i++) {
String list = Integer.toString(clients.get(i).getID()) + " - " + clients.get(i).getUsername() + " |";
if(pos == i) { list += " (you)"; }
if(clients.get(i).isAdmin()) { list += " (admin)"; }
clients.get(pos).send(list);
}
clients.get(pos).send("\n");
} else if(input.substring(0, 3).equals("/pm")) {
int pos = findClient(Integer.parseInt(input.substring(4, 9)));
clients.get(pos).send("<" + username + ">: " + input.substring(10));
} else if(input.length() > 12 && input.substring(0, 5).equals("/kick")) {
if(clients.get(findClient(id)).isAdmin()) {
int kID = Integer.parseInt(input.substring(6, 11));
String reason = input.substring(12);
clients.get(findClient(kID)).send("Kick: " + reason);
remove(kID);
} else {
clients.get(findClient(id)).send("You are not admin.");
}
} else if(input.length() > 10 && input.substring(0, 10).equals("/giveadmin")) {
if(clients.get(findClient(id)).isAdmin()) {
int aID = Integer.parseInt(input.substring(11));
clients.get(findClient(aID)).setAdmin(true);
clients.get(findClient(aID)).send("You have been made admin.\n");
} else {
clients.get(findClient(id)).send("You are not admin.");
}
} else {
clients.get(findClient(id)).runCommand(input);
}
} else {
for(int i = 0; i < clientCount; i++) {
if(clients.get(i).getID() != id) {
clients.get(i).send(username + ": " + input);
}
}
}
}
public synchronized void remove(int id) {
int pos = findClient(id);
if(pos >= 0) {
ServerThread toTerminate = clients.get(pos);
System.out.println("Remove client thread: " + id + " at " + pos);
try {
clients.get(pos).close();
} catch(IOException e) {
System.out.println("Error closing thread: " + e);
}
clients.remove(pos);
clientCount--;
try {
toTerminate.close();
} catch(IOException e) {
System.out.println("Error closing thread: " + e);
}
toTerminate.interrupt();
}
}
public void addThread(Socket socket) {
clients.add(new ServerThread(this, socket));
try {
clients.get(clientCount).open();
clients.get(clientCount).start();
clientCount++;
} catch(IOException e) {
System.out.println("Error opening thread: " + e);
}
}
public String getPasswd() { return passwd; }
public void setPasswd(String npasswd) { this.passwd = npasswd; }
}

Binary file not shown.

View File

@ -0,0 +1,118 @@
import java.net.*;
import java.io.*;
/**
* @author Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
* For details on the copyright, look at the COPYRIGHT file that came with
* this program.
*
*/
public class ServerThread extends Thread {
private Server server = null;
private Socket socket = null;
private int id = -1;
private String username = "User";
private DataInputStream streamIn = null;
private DataOutputStream streamOut = null;
private boolean run = false;
private boolean admin = false;
public ServerThread(Server _server, Socket _socket) {
super();
this.socket = _socket;
this.server = _server;
id = socket.getPort();
}
public void send(String msg) {
try {
streamOut.writeUTF(msg);
streamOut.flush();
} catch(IOException e) {
System.out.println(id + " Error sending: " + e.getMessage());
server.remove(id);
interrupt();
}
}
public void run() {
System.out.println("Server thread " + id + " running.");
while(run) {
try {
server.handle(id, username, streamIn.readUTF());
} catch(IOException e) {
System.out.println(id + " error reading: " + e.getMessage());
server.remove(id);
interrupt();
}
}
}
public void runCommand(String command) {
if(command.equals("/help")) {
send(" - /admin [passwd] -- Gain admin privileges.\n" +
" - /list -- Returns all the user's ID's and usernames.\n" +
" - /myID -- Returns your ID.\n" +
" - /myUserName -- Returns your username.\n" +
" - /pm [id] [msg] -- Sends a message to only one of the clients.\n" +
" - /setUserName [newusername] -- Change your username.\n" +
" - /help -- Show this information.\n" +
" - /quit -- Quit.\n");
if(admin) {
send("Admin commands:\n" +
" - /chgpasswd [newpasswd] -- Change the server admin password.\n" +
" - /giveadmin [id] -- Give another client admin as well.\n" +
" - /kick [id] [reason] -- Kick out a user and state a reason for the kick.\n");
}
} else if(command.length() > 6 && command.substring(0, 6).equals("/admin")) {
if(command.substring(7).equals(server.getPasswd())) {
admin = true;
send("You are now admin.\n");
} else {
send("Wrong password.\n");
}
} else if(command.equals("/myID")) {
send(Integer.toString(id) + "\n");
} else if(command.equals("/myUserName")) {
send(username + "\n");
} else if(command.length() > 12 && command.substring(0, 12).equals("/setUserName")) {
if(command.length() <= 13) {
send("You did not enter a new username.");
} else {
username = command.substring(13);
send("Your username is now: " + username + "\n");
}
} else if(admin && command.length() > 10 && command.substring(0, 10).equals("/chgpasswd")) {
if(command.length() > 11) {
server.setPasswd(command.substring(11));
} else {
send("You did not enter a new password.\n");
}
} else {
send("You have either entered an invalid command, or used an improper form.\n");
}
}
public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
streamOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
run = true;
}
public void close() throws IOException {
if(socket != null) { socket.close(); }
if(streamIn != null) { streamIn.close(); }
if(streamOut != null) { streamOut.close(); }
run = false;
}
public int getID() { return id; }
public String getUsername() { return username; }
public boolean isAdmin() { return admin; }
public void setAdmin(boolean a) { this.admin = a; }
}