diff --git a/README.md b/README.md
index 302642c..5b50f66 100644
--- a/README.md
+++ b/README.md
@@ -10,4 +10,295 @@ Bağlantı TCP tabanlı yüksek hızlı WebSocket protokolüne dayanır ve sunuc
## Proje tarafından uygulanan load balance teknolojisi
-
\ No newline at end of file
+
+
+# Geliştirici Dökümantasyonu
+
+## Kurulum
+
+### Proje ortamına kurulumu
+
+```html
+
+```
+
+### Geliştirme ortamına kurulumu
+
+```javascript
+const mwse = new MWSE({
+ endpoint: "wss://ws.saqut.com/" // MSWS kurulu sunucu adresi
+});
+mwse.scope(async () => {
+ // Bağlantı sağlandığında burası tetiklenir
+})
+```
+
+### Kendi bağlantı kimliğini öğrenme
+
+```javascript
+mwse.scope(async () => {
+ let me = mwse.peer('me'); // Kendi bağlantınız üzerinde işlem yaparken `me` olarak bahsedersiniz
+ console.log(me.socketId); // Her eşin tekil bir socketIdsi vardır
+})
+```
+
+
+### Sanal Adres ayırma / yeniden ayırma / kaldırma
+```javascript
+mwse.scope(async () => {
+ let me = mwse.peer('me');
+
+ /**
+ * Sanal adresler size veri gönderilmek istendiğinde veya etkileşime
+ * geçilmesi istendiğinde ona socketId gibi bir UUID yerine sizi temsil eden daha kısa
+ * ip adresi, sayı veya kısa bir kod ile aynı şeyleri yapmanıza olanak tanır.
+ * Aynı anda hem sanal ip adres, sayı ve kısa koduna sahip olabilirsiniz
+ * ancak aynı türden temsil koduna (mesela kısa koddan) birden fazla sahip olamazsınız
+ * Yeni bir bağlantı daha açmanız gerekir
+ **/
+
+ // Bağlantınıze özel sanal tekil ip adresi kaynağı ayırın
+ let ipadress = await me.virtualPressure.allocAPIPAddress();
+
+ // Bağlantınıze özel sanal tekil numara kaynağı ayırın
+ let numberaddress = await me.virtualPressure.allocAPNumber();
+
+ // Bağlantınıze özel sanal kod kaynağı ayırın
+ let shortcodeadress = await me.virtualPressure.allocAPShortCode();
+
+ // Bütün bu kaynakları yenileriyle değiştirmek için
+ // her birinin ayrı ayrı yeniden alma işlevleri vardır
+ // Bir adresi yenilediğinizde artık eski adres kullanılmaz olur
+ me.virtualPressure.reallocAPIPAddress();
+ me.virtualPressure.reallocAPNumber();
+ me.virtualPressure.reallocAPShortCode();
+
+ // Bütün bu kaynakları kaldırmak için her birinin ayrı ayrı
+ // bırakma işlevi vardır
+ // Bir adresi kullanmadığınızda artık bu adreslerden size
+ // ulaşılamaz olursunuz
+ await me.virtualPressure.releaseAPIPAddress();
+ await me.virtualPressure.releaseAPNumber();
+ await me.virtualPressure.releaseAPShortCode();
+
+ await me.virtualPressure.queryAPIPAddress();
+ await me.virtualPressure.queryAPNumber();
+ await me.virtualPressure.queryAPShortCode();
+})
+```
+
+### Farklı bir eşe erişme
+
+```javascript
+mwse.scope(async () => {
+ let peer = mwse.peer('325a8f7f-eaaf-4c21-855e-9e965c0d5ac9') // Diğer eşin socketId'sini belirtiyoruz
+ let me = mwse.peer('me');
+
+ // Eşin ulaşılabilir (online) olup olmadığını verir
+ let isOnline = await peer.isReachable();
+
+ if(isOnline)
+ {
+ // İleitşim kurmak için istek gönderiyoruz
+ await peer.requestPair();
+ }
+
+ // Bize gönderilecek olan istekleri dinliyoruz
+ me.on('request/pair', peer => {
+ // İstek gönderen kullanıcının bilgileri peer içinde bulunur
+ // iletişime devam etmek için isteği kabul ediyoruz
+ peer.acceptPair();
+ // veya istemiyorsak reddediyoruz
+ peer.rejectPair();
+ })
+
+ // Karşımızdaki kullanıcının ne cevap verdiğini
+ // anlamak için sistem ayrı ayrı cevaplar üretir
+
+ // Kabul ettiyse accept eventini tetikler
+ me.on('accepted/pair', peer => {
+ // İstek gönderen kullanıcının bilgileri peer içinde bulunur
+ })
+
+ // Reddettiyse veya iletişimi sonlandırmışsa
+ // end eventi tetiklenir
+ me.on('end/pair', peer => {
+ // Kullanıcının bilgileri peer içinde bulunur
+ })
+})
+```
+
+Eğer uygulamanızda bu şekilde bir erişim metodolojisi kullanmak istemiyorsanız
+pair sistemini elle kapatabilirsiniz
+
+```javascript
+mwse.scope(async () => {
+ let me = mwse.peer('me');
+
+ // Tüm kullanıcılar size mesaj iletebilir
+ await peer.disablePairAuth();
+
+ // Sadece eşleşmiş kullanıcılar size mesaj iletebilir
+ await peer.enablePairAuth();
+})
+```
+## Tünelleme ile mesajlaşma
+
+MWSE üzerinde karşılıklı mesajlaşma için
+ metodoloji bulunur bunlardan birisi serbest mesajlaşmadır ve
+ bu şekilde çalışır
+```javascript
+mwse.scope(async () => {
+ let me = mwse.peer('325a8f7f-eaaf-4c21-855e-9e965c0d5ac9');
+
+ // Tüm kullanıcılar size mesaj iletebilir
+ await peer.disablePairAuth();
+
+ // Bu şekilde serbest bir şekilde herhangi bir zamanda karşılıksız mesaj iletebilirsiniz
+ peer.send({
+ text: "Good morning"
+ })
+
+ // Kullanıcı her hangi bir mesaj gönderdiğinde burası tetiklenir
+ peer.on('message', message => {
+ if(text.message == "Good morning")
+ {
+ // Eğer mesaj için bir cevap bekliyorsa cevap veriyoruz
+ peer.send("You are welcome");
+ }else{
+ // Ancak mesaj önceden gönderdiğimiz isteğin cevabıysa görüntülüyoruz
+ console.log("Reply is :", message) // --> You are welcome
+ }
+ })
+})
+```
+2. yöntem ise el sıkışmalı mesajlaşmadır ve gönderdiğiniz bir mesaja verilen karşılık olarak
+sistem, gelen mesajın gönderdiğiniz hangi mesaja karşılık olarak gönderildiğini tuttuğu için
+request/response şeklinde ilerleyebilir
+
+```javascript
+mwse.scope(async () => {
+ let peer = mwse.peer('325a8f7f-eaaf-4c21-855e-9e965c0d5ac9');
+ let me = mwse.peer('me');
+
+ // Tüm kullanıcılar size mesaj iletebilir
+ await me.disablePairAuth();
+
+ // Bizden istenecek veriler için önceden cevapları hazırlıyoruz
+ me.on('request', ({body, response}) => {
+ switch(body.message)
+ {
+ case "Good morning":{
+ // do anything...
+ response("You are welcome")
+ break;
+ }
+ }
+ })
+
+
+ // Bu şekilde serbest bir şekilde herhangi bir zamanda karşılıksız mesaj iletebilirsiniz
+ let response = await peer.request({
+ message: "Good morning"
+ });
+
+ console.log(response) // response ---> You are welcome
+})
+```
+
+Bu şekilde hem okunabilirlik artar hemde mesajlar karşılıklı olarak etki-tepki şeklinde ilerler
+
+----
+
+
+### Oda kurma ve kapatma
+
+Oda sistemi kullanıcıların bir araya gelerek, tek seferde bir grubun
+toplu olarak birbirleriyle mesajlaşabileceği bir yapıdır.
+Kişiler birbirlerini bulabilir, toplu mesajlar iletebilirler, odaya
+katılabilir veya ayrılabilirler
+
+
+Odanın ayarlarını, odayı ilk oluşturan kişi belirler ve oda bir kez oluşturulduğunda yeniden aynı isimle oda açılamaz
+Oda türü (joinType) herkese açık `free`, davet ile `invite`, şifreli `password` veya herkese kapalı `lock` olabilir.
+
+```javascript
+
+mwse.scope(async () => {
+
+ let room = mwse.room({
+ name: "Oda ismi", // odanın görünür ismi
+ description: "Oda açıklaması", // odanın görünecek ismi
+ joinType: "free", // herkese açık oda
+ credential: "****", // varsa şifre
+ notifyActionInvite: false, // yeni biri katılmak istediğinde tüm peerlere haber iletme özelliği
+ notifyActionJoined: true, // yeni biri katıldığında tüm peerlere haber iletir
+ notifyActionEjected: true, // Biri odadan ayrıldığında tüm peerlere haber iletir
+ ifexistsJoin: false // true ayarlanırsa, oluşturma aşamasında oda zaten var yanıtı alırsa hata vermek yerine odaya katılır
+ });
+
+ // Verilen isime ait odaya katılmak için bu komut yeterlidir
+ await room.join(); // --> odaya katılırken sorun oluşursa hata fırlatır
+
+ // Verilen ayarlara sahip odayı oluşturmak için aşağıdaki komut yeterlidir
+ await room.createRoom(); // -> oda oluştururken sorun oluşursa hata fırlatır
+
+ // Var olan bir odadan ayrılmak için bu komut kullanılabilir
+ await room.eject();
+
+ // İçinde bulunduğu odanın tüm eşlerinin idsini verir
+ let peers = await room.fetchPeers();
+});
+```
+
+### Oda içerisinde iletişim
+
+Odaya katıldıktan sonra katılan kişiler `room` üzerinden mesaj iletebilirsiniz, verilen her mesajı sistem istisnasız tüm oda katılımcılarına iletmekten sorumludur
+Oda içerisindeki kişiler ile oda içindeki kişilerin listesini alarak özel iletişimede geçebilirsiniz ancak aynı odadaki kişiler sistem tarafında yinede güvenilir kabul edilmez
+Sistem pairAuth güvenliği kapalı olan kişilere mesajlar iletir ancak açık olan kullanıcıların her biri için ayrı ayrı eşleşme isteği göndermelisiniz
+
+```javascript
+
+mwse.scope(async () => {
+
+ let room = mwse.room({
+ name: "Oda ismi", // odanın görünür ismi
+ description: "Oda açıklaması", // odanın görünecek ismi
+ joinType: "free", // herkese açık oda
+ notifyActionJoined: true, // yeni biri katıldığında tüm peerlere haber iletir
+ ifexistsJoin: false // true ayarlanırsa, oluşturma aşamasında oda zaten var yanıtı alırsa hata vermek yerine odaya katılır
+ });
+
+ // Verilen ayarlara sahip odayı oluşturmak için aşağıdaki komut yeterlidir
+ await room.createRoom(); // -> oda oluştururken sorun oluşursa hata fırlatır
+
+ // Oda içerisinde mesaj gönderildiğinde gönderilen paketi dinlemek için aşağıdaki komut kullanılabilir
+ room.on('message', message => {
+ // Odaya `message` paketi iletildi
+ })
+
+ // Odaya yeni birisi katıldığında haber almak için aşağıdaki komut kullanılabilir
+ room.on('join', peer => {
+ // Odaya katılan kişinin bilgisi peerde tutulur
+ // Odaya katılan kişiyle bağlantı kurup, oda dışında kendisiyle iletişimede geçebilirsiniz
+ peer.requestPair();
+ })
+
+ // Odaya birisi ayrıldığında haber almak için aşağıdaki komut kullanılabilir
+ room.on('eject', peer => {
+ // Odadan ayrılan kişinin bilgisi peerde tutulur
+ })
+
+ // Odadaki herkese mesaj iletmek için room içerisindeki send komutu kullanılabilir
+ room.send({
+ message: "Good year !"
+ });
+
+ // Oda kapatıldığında close tetiklenir
+ room.on('close', () => { })
+});
+```
+
+### Odayı kapatma
+
+Odalar odaya ait olan bağlantılar üzerine kurulur, tüm bağlantılar odadan çıktığında oda otomatik olarak kapatılır
\ No newline at end of file
diff --git a/Source/Client.js b/Source/Client.js
index 9824ba9..98e2835 100644
--- a/Source/Client.js
+++ b/Source/Client.js
@@ -27,6 +27,9 @@ function Client()
* @type {Set}
*/
this.rooms = new Set();
+ /**
+ * @type {Set}
+ */
this.pairs = new Set();
this.requiredPair = false;
@@ -151,7 +154,7 @@ Client.prototype.rejectPeerRequest = function(client){
this.sync('pairs');
client.send([{
from: this.id
- },'rejected/pair']);
+ },'end/pair']);
};
/**
* @param {Client|string} client
@@ -164,6 +167,9 @@ Client.prototype.isPaired = function(client){
}
return client.pairs.has(this.id) && this.pairs.has(client.id);
};
+/**
+ * @returns {string[]}
+ */
Client.prototype.pairList = function(){
return [...this.pairs.values()].filter(e => this.isPaired(e));
};
diff --git a/Source/Services/Auth.js b/Source/Services/Auth.js
index abb6567..1ce2895 100644
--- a/Source/Services/Auth.js
+++ b/Source/Services/Auth.js
@@ -127,10 +127,28 @@ addService(({
client.rejectPeerRequest(pairclient);
break;
}
+ case 'end/pair':{
+ if(Client.clients.has(to)){
+ return end({
+ status: 'fail',
+ message: 'CLIENT-NOT-FOUND'
+ })
+ };
+ let pairclient = Client.clients.get(to);
+ if(!pairclient.pairs.has(client.id))
+ {
+ return end({
+ status: 'success',
+ message: 'NOT-PAIRED'
+ })
+ }
+ client.rejectPeerRequest(pairclient);
+ break;
+ }
case 'pair/list':{
end({
type:'pair/list',
- value: pairList
+ value: client.pairList()
})
break;
}
@@ -149,38 +167,6 @@ addService(({
}
break;
}
- // case 'auth/check':{
- // let auth = client.store.has('user');
- // return end({
- // value: auth
- // })
- // }
- // case 'auth/login':{
- // if(username == '*' && password == '*')
- // {
- // return end({
- // status: 'success'
- // })
- // }else{
- // return end({
- // status: 'fail'
- // })
- // }
- // }
- // case 'auth/logout':{
- // let auth = client.store.has('user');
- // if(auth)
- // {
- // client.store.delete('user');
- // return end({
- // status: 'success'
- // })
- // }else{
- // return end({
- // status: 'fail'
- // })
- // }
- // }
case 'auth/info':{
client.info.set(name, value);
let clients = client.getSucureClients();
diff --git a/frontend/Peer.ts b/frontend/Peer.ts
index 92c3df7..422117e 100644
--- a/frontend/Peer.ts
+++ b/frontend/Peer.ts
@@ -119,6 +119,68 @@ export default class Peer extends EventTarget
value: 'disable'
});
}
+ async requestPair()
+ {
+ let {message,status} = await this.mwse.EventPooling.request({
+ type:'request/pair',
+ to: this.socketId
+ });
+ if(
+ message == "ALREADY-PAIRED" ||
+ message == "ALREADY-REQUESTED"
+ )
+ {
+ console.warn("Already paired or pair requested")
+ };
+ if(status == "fail")
+ {
+ console.error("Request Pair Error",status, message);
+ return false;
+ }
+ return true;
+ }
+ async endPair()
+ {
+ await this.mwse.EventPooling.request({
+ type:'end/pair',
+ to: this.socketId
+ });
+ this.forget();
+ }
+ async acceptPair()
+ {
+ let {message,status} = await this.mwse.EventPooling.request({
+ type:'accept/pair',
+ to: this.socketId
+ });
+ if(status == "fail")
+ {
+ console.error("Pair Error",status, message);
+ return false;
+ }
+ return true;
+ }
+ async rejectPair()
+ {
+ let {message,status} = await this.mwse.EventPooling.request({
+ type:'reject/pair',
+ to: this.socketId
+ });
+ if(status == "fail")
+ {
+ console.error("Pair Error",status, message);
+ return false;
+ }
+ return true;
+ }
+ async getPairedList() : Promise
+ {
+ let {value} = await this.mwse.EventPooling.request({
+ type:'pair/list',
+ to: this.socketId
+ });
+ return value;
+ }
async send(pack: any){
let isOpenedP2P = this.peerConnection;
let isOpenedServer = this.mwse.server.connected;
diff --git a/frontend/index.ts b/frontend/index.ts
index 2b1feee..cd08b17 100644
--- a/frontend/index.ts
+++ b/frontend/index.ts
@@ -99,13 +99,30 @@ export default class MWSE extends EventTarget {
})
this.EventPooling.signal("pair/info", (payload : {from : string,name: string, value: string | number | boolean}) => {
let {from, name, value} = payload;
-
let peer = this.peer(from);
-
peer.info.info[name] = value;
-
peer.emit("info", name, value);
})
+ this.EventPooling.signal("request/pair", (payload : {from : string,info: any}) => {
+ let {from, info} = payload;
+ let peer = this.peer(from);
+ peer.info.info = info;
+ peer.emit("request/pair", peer);
+ this.peer('me').emit('request/pair', peer);
+ })
+ this.EventPooling.signal("accepted/pair", (payload : {from : string,info: any}) => {
+ let {from, info} = payload;
+ let peer = this.peer(from);
+ peer.info.info = info;
+ peer.emit("accepted/pair", peer);
+ this.peer('me').emit('accepted/pairr', peer);
+ })
+ this.EventPooling.signal("end/pair", (payload : {from : string,info: any}) => {
+ let {from, info} = payload;
+ let peer = this.peer(from);
+ peer.emit("endPair", info);
+ this.peer('me').emit('endPair', from, info);
+ })
}
public room(options: IRoomOptions | string) : Room
{